模板类型!=扣除类型

时间:2017-08-16 22:52:50

标签: c++ templates c++17

我试图将类型的友好名称作为模板类型名称,因为我需要在函数中的几个位置使用该名称。该类型是根据参数包中其他模板参数的数量推断出来的,如下所示:

#include <cassert>
#include <functional>
#include <type_traits>

template < typename ... TArgs, typename Functor = std::function< std::conditional_t< sizeof...(TArgs) == 0, int (), int (TArgs...) > > >
void DoStuff(const Functor & func, TArgs ... args) {
    if constexpr (sizeof...(TArgs) == 0)
        assert(typeid(Functor).hash_code() == typeid(std::function<int ()>).hash_code());
    else
        assert(typeid(Functor).hash_code() == typeid(std::function<int (TArgs...)>).hash_code());
}

int main(int argc, char * argv[]) {
    DoStuff([] () { return 5; });
    DoStuff([] (int a) { return a; });

    return 0;
}

这个编译很好,但两个断言都失败了,因为别名Functor实际上不是std::function<>。另一方面,如果我更改代码以在Functor调用中重复typeid的定义,则它可以完美地运行,如下所示:

#include <cassert>
#include <functional>
#include <type_traits>

template < typename ... TArgs, typename Functor = std::function< std::conditional_t< sizeof...(TArgs) == 0, int (), int (TArgs...) > > >
void DoStuff(const Functor & func, TArgs ... args) {
    if constexpr (sizeof...(TArgs) == 0)
        assert(typeid(std::function< std::conditional_t< sizeof...(TArgs) == 0, int (), int (TArgs...) > >).hash_code() == typeid(std::function<int ()>).hash_code());
    else
        assert(typeid(std::function< std::conditional_t< sizeof...(TArgs) == 0, int (), int (TArgs...) > >).hash_code() == typeid(std::function<int (TArgs...)>).hash_code());
}

int main(int argc, char * argv[]) {
    DoStuff([] () { return 5; });
    DoStuff([] (int a) { return a; });

    return 0;
}

为什么第一个声明(使用typname Functor = ...)不正确?是否有不同的方法来制作别名?请注意,在回答第二个问题时,如果解决方案是const表达式,则可以使用constexpr,但这些示例仅为typeid

1 个答案:

答案 0 :(得分:1)

  

为什么第一个声明(使用typename Functor = ...)不正确?

您正在为模板参数Functor提供默认类型。但是,仅在未以其他方式指定或推导出类型时才使用默认类型。在这种情况下,模板推导将在两种情况下推导出Functor,无论是调用它的lambda的唯一类型(当Args...推导为空包时)。

这类似于提供它们时未使用的默认函数参数。

我不确定您的assert()应该完成什么,但如果您要检查类型,则应使用static_assert