我在与别名模板的上下文中偶然发现了关于模板参数推导的一些行为,我不理解 .

基本设置如下:

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

然后我尝试推导出value_id实例化的模板参数(例如在下面显示的特征类模板中) . 我的第一种方法是直接在部分模板特化的参数列表中使用value_id别名模板:

// 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 {};

我意识到第一种方法不起作用后,我的第二种方法是直接将value_id定义写入参数列表,然后该参数列表适用于MSVC和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?

正如Johannes Schaub在一篇相关的文章中写道:

“他们[别名模板]与等效代码一样可以推导,而不使用模板别名 . ”

我还为 both 方法实现了另一个别名模板:

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

所以下面的trait类模板能够推导出id实例化的模板参数:

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