SwiftMango
SwiftMango

Reputation: 15284

static_assert not evaluated in template parameter

I have this code to determine if the template type has foo():

template <typename T, typename = void>
struct has_foo : std::false_type {};

template <typename T>
struct has_foo<T, std::void_t<decltype(std::declval<T&>().foo()) > > : std::true_type {};

template <typename T>
void has_foo_f(){
    static_assert(has_foo<T>::value, "Type does not have foo()."); 
}

Then I have the bar function that takes a template parameter with foo:

template<typename T, typename = decltype(has_foo_f<T>())>
void bar(){}

In the main file, I have a fail case:

//Foo does not implement foo(). It should fail!
template<typename T>
class Foo{};

int main()
{
    has_foo_f<Foo<int>>(); //This line fail
    bar<Foo<int>>();       //This line does not fail
}

When I call has_foo_f directly, the compiler gives me static assertion error, which is correct. However when I call bar<Foo<int>>, the compiler successfully compiled it without error.

Why does this happen? Why is the static_assert not evaluated? I understand decltype does not need to evaluate static_assert to get the type info, but isn't static_assert always evaluated at compile time?

Upvotes: 0

Views: 119

Answers (1)

user7860670
user7860670

Reputation: 37468

Operand of decltype is not evaluated and therefore does not require function definition to exist (or return type being complete) while function template is instantiated when the specialization is referenced in a context that requires a function definition to exist. So you need to instantiate function template for check inside of function body to take place:

template<typename T, auto Dummy = &has_foo_f<T>>
void bar(){}

Upvotes: 2

Related Questions