3

I stumbled over some behaviour regarding template argument deduction in context with alias templates, I am not understanding.

The basic setup is as follows:

#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>...>;

I then tried to deduce the template arguments of a value_id instantiation (as for example in the below shown trait class template). My first approach was to use the value_id alias template directly in the argument list of the partial template specialization:

// 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 wasn't working, was to directly write the value_id definition into 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 is the first approach not working, when the second one is?

As Johannes Schaub wrote in a related post:

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

I also defined a further alias template for which both approaches are functional:

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

So the below trait class template is able to deduce the template arguments of an id instantiation:

template<typename tpID>
struct is_id : std::false_type {};
template<typename ...tpTypes>
struct is_id<id<tpTypes...>> : std::true_type {};
Community
  • 1
  • 1
N. Huch
  • 91
  • 1
  • 4

0 Answers0