ARTICLE AD BOX
From https://godbolt.org/z/eddbGqaxh (https://godbolt.org/z/bnzzMn8nK):
// Example program #include <iostream> #include <string> namespace bar { template<typename T> concept has_foo = std::same_as<std::true_type, decltype(enable_foo(std::declval<T>()))>; } namespace my { struct Foo{}; } namespace bar { consteval std::true_type enable_foo(my::Foo); } int main() { bool const enable_foo_ = std::same_as<std::true_type, decltype(bar::enable_foo(std::declval<my::Foo>()))>; bool const has_foo_ = bar::has_foo<my::Foo>; std::cout << "enable_foo " << enable_foo_ << "\n"; std::cout << "has_foo " << has_foo_ << "\n"; }I don't understand why enable_foo_ evaluates to true and has_foo_ to false.
If I move the enable_foo(my::Foo) declaration before the concept or the Foo definition into namespace bar (but after concept) everything is fine.
I expected that the concept is evaluated at point of instantiation and not declaration.
When and where are C++ concepts instantiated?
15.2k6 gold badges44 silver badges103 bronze badges
6
Concepts are never instantiated, they are always evaluated as an expression whenever they appear (which might be part of a different templated entity being instantiated) [temp.concepts]p5:
A concept is not instantiated.
However, names are always looked up from where they physically appear ([temp.res.general]p1).
At the concept definition, bar::enable_foo has not yet been declared so cannot be found by unqualified name lookup and argument-dependent lookup does not include the namespace bar, so it is not found.
When you later do enable_foo_ = std::same_as<...>;, bar::enable_foo is visible because it has been declared previously.
44.4k3 gold badges82 silver badges110 bronze badges
Explore related questions
See similar questions with these tags.
