Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 了解别名模板_C++_Templates_Alias_Enable If_C++17 - Fatal编程技术网

C++ 了解别名模板

C++ 了解别名模板,c++,templates,alias,enable-if,c++17,C++,Templates,Alias,Enable If,C++17,我问了一个有多处代码引用的问题: template <typename...> using void_t = void; 模板 使用void\u t=void; 我相信我有一个普遍的误解: 为什么不在enable\u if\t或conditional\u t语句中计算传递到别名模板中的任何模板参数? 上面的代码是否只是一次对多个模板参数执行enable\u if\t 其次,我认为我对void\u t的作用有一个特定的误解。声明C++17标准定义了void\t。以下是我没有得到的:

我问了一个有多处代码引用的问题:

template <typename...>
using void_t = void;
模板
使用void\u t=void;
我相信我有一个普遍的误解:

为什么不在
enable\u if\t
conditional\u t
语句中计算传递到别名模板中的任何模板参数?

上面的代码是否只是一次对多个模板参数执行
enable\u if\t

其次,我认为我对
void\u t
的作用有一个特定的误解。声明C++17标准定义了
void\t
。以下是我没有得到的:


无效不是一个任意的名字吗?如果我仍然必须使用void\u t=void定义
模板
无论我打算在哪里使用
void\t
标准化任意名称有什么意义?

在Barry的例子中,来自您的链接问题:

template<typename T, typename = void>
struct has_to_string
: std::false_type { };

template<typename T>
struct has_to_string<T, 
    void_t<decltype(std::to_string(std::declval<T>()))>
    > 
: std::true_type { };
前一个版本更容易阅读,而且
void\u t
不需要
decltype
即可工作

如果
void\t
在您的实现中可用,则无需重新定义它。标准化后,它将与标准中的任何其他别名模板一样可用

这样考虑:如果
T
int
,它有一个有效的
std::to_字符串
重载,则演绎将如下所示:

template<>
struct has_to_string<int,void>
: std::true_type { };
由于默认参数,
具有\u到\u字符串
->
具有\u到\u字符串
。因此,让我们来寻找带有这些参数的
has_to_string
的专门化

template<typename T>
struct has_to_string<T, 
    void_t<decltype(std::to_string(std::declval<T>()))>
    > 
: std::true_type { };
现在我们的专业化如下所示:

template<>
struct has_to_string<int,void>
: std::true_type { };
放弃该专门化后,我们回到主模板:

template<typename T, typename = void>
struct has_to_string
: std::false_type { };
模板
结构具有\u到\u字符串
:std::false_type{};

因此,
has_to_string
继承自
std::false_type
我认为所示示例并未真正说明
void_t
的用途,因为它只显示了一个用例,但当您查看

template<typename T>
struct has_to_string<T, 
    void_t<decltype(std::to_string(std::declval<T>()))>
    > 
: std::true_type { };
如您所见,即使主模板也使用
void\t
来提高可读性,因为它现在与专门化匹配。这不是绝对必要的,但我喜欢。真正的力量来自于你对其他选择的思考。如果没有
void\t
,专业化现在就更复杂了:

template< class T >
struct has_type_member<T, decltype(typename T::type, void())>
: std::true_type { }

整个表达式变得更长、更复杂,并且可能会遇到您忘记处理的边缘情况。这就是
void\u t
真正有帮助的地方,其他用法只是一个小小的改进,它们增加了一致性。

所以你说
模板使用void\u t=void将在其中一个标准标题中定义?是的,完全正确。然后,您只需
#包含
,并使用
std::void\t
@JonathanMee,它应该变成C++17@所以我想我明白了:我不能使用
enable\u if\u t
因为没有“if\u this\u compiles”元函数,我需要这样做:
enable\u if\u t
如此有效,我使用
void\u t
作为
enable\u if\u t
,带有“if\u this\u compiles”条件和
void
返回类型,但是有了这个构造,
decltype
SFINAE和
void\u t
支持它。是的,
void\u t
只是一个任意的名称。但是如果它是标准化的,它的拼写应该是
std::void\t
,这样你就不必自己定义它了。同样的原因是,如果
和其他类型特征被标准化,那么启用它-这样其他程序员就可以识别它们,所有的用户就不必不断地重新定义它们。我可以看出这对于可变模板也是多么有用。@JonathanMee和更多。。。
void\u t
本身的易变性甚至允许同时出现多种情况,想想
void\u t
template<typename T>
struct has_to_string<T, 
    void_t<decltype(std::to_string(std::declval<T>()))>
    > 
: std::true_type { };
template<typename T>
struct has_to_string<T, 
    decltype(std::to_string(std::declval<T>()), void())
    > 
: std::true_type { };
// primary template handles types that have no nested ::type member
template< class, class = void_t<> >
struct has_type_member
: std::false_type { };

// specialization recognizes types that do have a nested ::type member
template< class T >
struct has_type_member<T, void_t<typename T::type>>
: std::true_type { }
template< class T >
struct has_type_member<T, decltype(typename T::type, void())>
: std::true_type { }
template< class T >
struct has_type_member<T, decltype(std::declval<typename T::type>(), void())>
: std::true_type { }