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?

philipxy's user avatar

philipxy

15.2k6 gold badges44 silver badges103 bronze badges

Feuerteufel's user avatar

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.

Artyer's user avatar

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.