如果您可以等待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;
}
作为@T.C.在 cmets 中声明,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_t1 和type_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>。