c++ - 不在模板中声明类型名称的用例是什么?

标签 c++ templates coding-style typename

有时我会看到下面的声明:

template<typename>  // <-- not "typename T"
struct A { ... };

此类声明的用例是什么。这些是有用的还是只是风格问题?

最佳答案

您真的看到它用于模板定义,而不是用于模板声明(仅)吗?

一些用途:

// declaration only: the parameter name has no use beyond documentation
template<typename>
struct A;

// this is fine
template<typename T>
void eat_an_a(A<T> a);

// later, we can name the parameter to use it
template<typename T>
struct A { ... };

// C++0x only
template<
    typename T
    // We don't care for the actual type (which will default to void)
    // the goal is sfinae
    , typename = typename std::enable_if<
        std::is_array<typename std::decay<T>::type>::value
    >::value
>
void
f(T&& t);

// We still don't care to name that defaulted parameter
template<typename T, typename>
void f(T&& t)
{ ... }

Johannes 已经对您所链接的特定案例进行了解释,但显然您发现它并不令人满意。我将向您介绍这是如何工作的。让我们假设一个任意特征类:

// no definition
template<typename TypeToExamine, typename ImplementationDetail = void>
struct trait;

我正在详细说明类型参数在它们的名称中的作用。现在这个声明允许的,因为第二个参数是默认的,是一点语法糖。无论在哪里trait<U>出现,它完全就好像我们写了trait<U, void>已经写好了。现在让我们为特征的基本情况提供一个定义:

// assume previous declaration is still in scope so we do not default
// the second parameter again
template<typename T, typename> struct trait: std::false_type {};

这不是一个非常有用的特性。现在当我们写 trait<U> , 这是 trait<U, void> 的缩写,我们最终得到这个定义。这意味着 trait<U>::value是有效的,实际上是 false .让我们通过添加 secret 成分使我们的类更有用:

template<typename> struct void_ { typedef void type; };
// again, assume previous declarations are in scope
template<typename T, typename void_<decltype( T() + T() )>::type>
struct trait: std::true_type {};

同样,当我们写 trait<U> , 就好像我们写了 trait<U, void> .部分特化不会改变这一点(这是不允许的)。但是我们在查询trait<U>::value时应该使用什么定义呢? ?好吧,首先,我们必须知道专业应该匹配什么;或者,神秘的第二个参数是什么 typename void_<decltype( T() + T() )>::type

最简单的情况是 U() + U()是病式的。然后 SFINAE 介入,就好像特化不存在一样;因此我们得到了非专业定义,并且valuefalse .但是如果U() + U()是良构的,那么decltype产生一个类型,整体变成 void , 因为对于所有类型 void_<T>::typevoid .所以这意味着我们有一个形式的特化 trait<T, void> .这可以匹配 trait<U> , 简单匹配 TU .现在valuetrue .

但是如果专门化已经被编写

template<typename T>
struct trait<T, decltype( T() + T() )>: std::true_type {};

那么唯一使用它的方法就是写trait<U, decltype(U() + U())> , 除非 decltype(U() + U())碰巧是空的。记住,trait<U>是糖 trait<U, void> .所以trait<int>永远不会匹配我们的专业,因为后者的形式是 trait<int, int> .

因此 void_扮演的角色总是具有 trait<T, void> 形式的特化如果他们不是 SFINAE 就出来了。因为我们根本不关心使用类型参数,所以它没有命名。

关于c++ - 不在模板中声明类型名称的用例是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6561212/

相关文章:

c++ - 限制函数指针的转换

c++ - 在 C++ 中使用模板回调函数

c++ - 通过参数启用时 std::enabled_if 如何工作

coding-style - 编写冗长的单行代码是一种不好的做法吗?

c++ - 使用链表读取基本多项式

c++ - 使用 std::mutex 释放和获取

c++ - 如何将 cv::Mat 转换为带颜色的 pcl::pointcloud

templates - CSS3 样式表模板

Python:将 try 代码与 try 语句放在同一行有什么好处吗?

installation - 是否有任何 NSIS 最佳实践或编码标准?