Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Use of variable template in concept contraints yields compilation errors

Consider the following concept:

template< typename T, std::size_t Value >
concept Is_ = requires(T&&)
{
    requires Value == std::remove_cvref_t< T >::value;
};

Associated with the function overloads:

template< Is_< 2 > T >
void foo(T&&)
{
    std::cout << "Value is 2!" << std::endl;
}

template< typename T >
void foo(T&&)
{
    std::cout << "Either no value or it isn't 2!" << std::endl;
}

Finally, let’s play with the above functions:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

foo(std::integral_constant< std::size_t, 2 >{}); // Choose the constrained overload
foo(std::tuple{}) // Choose the generic impl

Now if I define the following helper variable template:

template< typename T >
inline constexpr auto t_value = T::value;

And use it in the concept for brevity’s sake:

template< typename T, std::size_t Value >
concept Is_ = requires(T&&)
{
    requires Value == t_value< std::remove_cvref_t< T > >;
};

I now get this compiler error:

main.cpp: In instantiation of ‘constexpr const auto t_value’:

main.cpp:11:23: required by substitution of ‘template requires Is_<T, 2> void foo(T&&) [with T = int]’

main.cpp:27:8: required from here

main.cpp:6:29: error: ‘value’ is not a member of ‘int’

6 | constexpr auto t_value = T::value;

Having invalid type aliases is however perfectly fine.

MVCE is available here: https://coliru.stacked-crooked.com/a/653bb52448ca1db3

Where does this behavior come from?

>Solution :

It happens because the instantiation of the variable template is not in the "immediate context" of the concept when it is being substituted and verified. Invalid types and expressions are only (and always have been) sfinae-friendly in the immediate context of the template argument substitution where they appear.

And since t_value is entirely different template, any failure that would occur during its instantiation would not be a "soft failure" in a concept that uses one of its specializations.


By the way, to address the original link in your post. Alias templates have special provisions that oftentimes allow them to be a drop-in replacement where whatever they are aliasing would appear (think how std::enable_if_t is also sfinae friendly, and always has been). When you checked the t_value_type alias in the conecpt before the value, it already failed in a sfinae-friendly way, so the concept evaluated to false (since the constraints were checked in order of appearance).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading