c++ - 我可以使单个模板<typename T> 应用于多个定义/声明吗?

标签 c++ templates idioms syntactic-sugar

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

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

即有 template <typename T>适用于多个定义/声明。 { }上面的语法无法编译;还有其他表达方式吗?

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

最佳答案

如果可以等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.在评论中指出, 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)>;
}

需要std::decay_t在这种情况下,如果我们传入一个指针或带有某些 cv 限定符的引用,就会出现这种情况。我们只需要底层类型。

然后强制执行 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> 这一切是否值得多来几次。

关于c++ - 我可以使单个模板<typename T> 应用于多个定义/声明吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31802742/

相关文章:

c++ - ‘*’ token 之前的预期初始值设定项

c++ - 如何在 C++ 和 Lua 之间来回传递大型结构

c++ - 如果模板参数是函数指针

silverlight - 将模板属性值绑定(bind)到模板化控件属性

go - 异步 api 上的阻塞函数是惯用的吗?

c++ - C++ clone idiom 中协变返回类型的有用性?

c++ - GlobalMemoryStatusEx 不考虑新阵列

c++ - 链表访问冲突

c++ - 就内存使用而言,模板 + 仿函数/lambdas 不是最理想的吗?

c++ - 如何使用 C++11 中的函数式编程从 map 中获取键?