我可以将单个模板<typename t =“”>应用于多个定义/声明吗?

时间:2015-08-04 07:05:03

标签: c++ templates idioms syntactic-sugar

在C ++中,我希望能够说:

template <typename T> {
void foo(T t1);
void bar(T t1, T t2);
}

即。让template <typename T>适用于多个定义/声明。上面的{ }语法不能编译;还有另一种表达方式吗?

注意:包装结构/类中的函数不会,我想要的东西既简洁又没有任何虚拟实体。

1 个答案:

答案 0 :(得分:4)

如果您可以等待C++17 concepts,则可以使用auto参数类型而不是使用模板。

说我有以下C ++ 17函数:

auto func(auto x, auto y){
    return x + y;
}

这可以用C ++ 14重写,如下所示:

template<typename T, typename U>
auto func(T x, U y){
    return x + y;
}

可以在C ++ 11中再次重写这样的内容:

template<typename T, typename U>
auto func(T x, U y) -> typename std::decay<decltype(x + y)>::type{
    return x + y;
}

as @ T.C.在注释中声明,std::decay在这里是必要的,因为c ++ 14中自动返回类型的语义将衰减最终语句,而decltype(x + y)不会衰减表达式类型。如果我们想要不衰减返回表达式类型,我们会写:

// template here for c++14
decltype(auto) func(auto x, auto y){
    return x + y;
}

因此,根据这些信息,我们可以重写这样的函数:

void foo(auto t1);
void bar(auto t1, auto t2);

请记住,如果我们需要引用参数的类型,我们需要使用decltype

如果您打算广泛使用类型模板是一个更好的主意,但为了保持函数定义中函数声明的简洁性,我们可以为类型编写一些using语句:

void bar(auto t1, auto t2){
    using type_t1 = std::decay_t<decltype(t1)>;
    using type_t2 = std::decay_t<decltype(t2)>;
}

如果我们使用某些cv限定符传入指针或引用,则会出现std::decay_t在这种情况下的需要。我们只想要基础类型。

然后,要强制type_t1type_t2的基础类型与示例中的相同,我们可以使用SFINAE排除bar的所有实例化不:

auto bar(auto t1, auto t2) -> std::enable_if_t<std::is_same<std::decay_t<decltype(t1)>, std::decay_t<decltype(t2)>>::value>{
    using type = std::decay_t<decltype(t1)>;
}

再次,衰减类型,以便如果我们得到指针,我们正在比较基础类型。

只要记住问自己这是否值得,只需再多写template<typename T>几次。