Alias ​​template deduction argument

I stumbled upon some behavior regarding template argument deduction in context with alias templates, I don't understand.

The basic setup looks like this:

#include <type_traits>
#include <iostream>

// class-template:
template<typename tpProxy, typename ...tpElements>
struct basic_id {};

// alias template for the above defined class-template:
template<typename tpTypeValue, tpTypeValue ...tpValues>
using value_id = basic_id<std::integral_constant<tpTypeValue, 0>,
    std::integral_constant<tpTypeValue, tpValues>...>;

      

Then I tried to infer the template arguments of the value_id instance (like in the trait class template below). My first approach was to use the alias value_id template directly in the template partial specialization argument list:

// 1st approach of a traits class for value_id:
template<typename tpValueID>
struct is_value_id_1st_approach : std::false_type {};
template<typename tpTypeValue, tpTypeValue ...tpValues>
struct is_value_id_1st_approach<value_id<tpTypeValue, tpValues...>> : std::true_type {};

      

My second approach, after realizing that the first one didn't work, was to directly write the definition of value_id to the argument list, which then worked for MSVC as well as GCC:

// 2nd approach; this time with directly given template-instantiation:
template<typename tpValueID>
struct is_value_id_2nd_approach : std::false_type {};
template<typename tpTypeValue, tpTypeValue ...tpValues>
struct is_value_id_2nd_approach<basic_id<std::integral_constant<tpTypeValue, 0>,
    std::integral_constant<tpTypeValue, tpValues>...>> : std::true_type {};

int main() {
    using my_value_id = value_id<int, 1, 2, 3>;
    std::cout << "is_value_id_1st_approach = " << std::boolalpha <<
        is_value_id_1st_approach<my_value_id>::value << std::endl; // false
    std::cout << "is_value_id_2nd_approach = " << std::boolalpha <<
        is_value_id_2nd_approach<my_value_id>::value << std::endl; // true
}

      

But why doesn't the first approach work when the second?

As Johannes Schaub wrote in a related post :

"They [templates alias] are output as equivalent code without using template aliases."

I also defined the following alias pattern for which both are fine:

template<typename ...tpTypes>
using id = basic_id<void, tpTypes...>;

      

So the template template below can output template arguments to instantiate id:

template<typename tpID>
struct is_id : std::false_type {};
template<typename ...tpTypes>
struct is_id<id<tpTypes...>> : std::true_type {};

      

+3


source to share





All Articles