iam*_*ind 7 c++ templates coding-style typename
有时我会在下面看到一种声明:
template<typename> // <-- not "typename T"
struct A { ... };
Run Code Online (Sandbox Code Playgroud)
这种声明的用例是什么?那些有用还是仅仅是风格问题?
您是否真的看到用于模板定义,而不是仅用于模板声明(仅限)?
一些用途:
// 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)
{ ... }
Run Code Online (Sandbox Code Playgroud)
约翰内斯给出了你所联系到的特殊情况的解释,但显然你发现它并不令人满意.我将带你了解它的工作原理.让我们假设一个任意的特质类:
// no definition
template<typename TypeToExamine, typename ImplementationDetail = void>
struct trait;
Run Code Online (Sandbox Code Playgroud)
我在名字中拼写出类型参数的作用.现在这个声明允许什么,因为第二个参数是默认的,有点语法糖.无论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 {};
Run Code Online (Sandbox Code Playgroud)
这不是一个非常有用的特质.现在,当我们写trait<U>
,这是短期的trait<U, void>
,我们结束了这个定义.这意味着它trait<U>::value
是有效的并且实际上是有效的false
.让我们通过添加秘密成分使我们的课更有用:
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 {};
Run Code Online (Sandbox Code Playgroud)
再一次,当我们写作时trait<U>
,就像我们写的一样trait<U, void>
.部分特化不会改变(不允许).但是当我们查询时,我们应该使用什么定义trait<U>::value
?那么,首先,我们必须知道什么是专业化的匹配; 或者,神秘的第二个论点是typename void_<decltype( T() + T() )>::type
什么?
最简单的情况是何时U() + U()
形成不良.然后SFINAE开始了,就好像专业化不存在一样; 因此我们得到了非专业化的定义,而且value
是false
.然而U() + U()
,如果格式良好,那么decltype
产生一个类型,整体变成void
,因为对于所有类型void_<T>::type
都是void
.所以这意味着我们有一个专业化的形式trait<T, void>
.这可以匹配trait<U>
,简单地匹配T
用U
.现在value
是true
.
但是,如果专业化将被写入
template<typename T>
struct trait<T, decltype( T() + T() )>: std::true_type {};
Run Code Online (Sandbox Code Playgroud)
那么它的唯一使用方式就是写作时trait<U, decltype(U() + U())>
,除非 decltype(U() + U())
发生错误.记住,trait<U>
是糖trait<U, void>
.所以trait<int>
永远不会匹配我们的专业化,因为后者是形式trait<int, int>
.
因此void_
,trait<T, void>
如果它们不是SFINAE,那么它总是具有形式的特化.因为我们根本不关心使用type参数,所以它没有命名.
归档时间: |
|
查看次数: |
1099 次 |
最近记录: |