我想检查是否存在接受T参数类型的非成员函数.为此,我使用void_t了Walter E. Brown先生在cppcon上提出的"技巧"(同样的技巧没有任何问题,检查是否存在成员类型或成员函数).
#include <iostream>
#include <type_traits>
template<typename...>
using void_t = void;
void Serialize(float&)
{
}
template<typename T, typename = void>
struct has_external_serialize : std::false_type
{
};
template<typename T>
struct has_external_serialize<T, void_t<decltype(Serialize(std::declval<T&>()))>> : std::true_type
{
};
void Serialize(int&)
{
}
int main(int argc, const char * argv[])
{
std::cout<<has_external_serialize<float>::value<<has_external_serialize<int>::value;
}
Run Code Online (Sandbox Code Playgroud)
11使用GCC 10编译时以及使用clang(xcode 5.1.1)编译时,将打印此代码.
我的问题是 - 这段代码是否正确?如果是,是否存在clang中的错误或GCC中的错误,或者代码是在某个"实现定义"区域中,我不能假设它在所有平台上都有相同的行为?
编译器之间的差异是由以下定义引起的void_t:\n我的 is_complete 类型特征的实现是否存在编译器错误?简而言之,该标准并不清楚别名模板特化中未使用的参数是否会导致替换失败或被简单地忽略。CWG 第 1558 期的决议澄清了较短的定义void_t应该有效。
通过使用解决了这个问题
\n\ntemplate<typename... Ts>\nstruct make_void { typedef void type;};\n\ntemplate<typename... Ts>\nusing void_t = typename make_void<Ts...>::type;\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\xc2\xa714.6.4.2 [temp.dep.candidate]:
\n\n\n\n\n对于依赖于模板参数的函数调用,可以使用通常的查找规则 (3.4.1、\n 3.4.2、3.4.3) 来查找候选函数,但以下情况除外:
\n\n\n
\n\n- 对于使用非限定名称查找 (3.4.1) 或限定名称查找 (3.4.3) 的查找部分,仅查找模板定义上下文中的函数声明。
\n- 对于使用关联命名空间 (3.4.2) 的查找部分,仅找到在模板定义上下文或模板实例化上下文中找到的函数声明。
\n如果函数名称是非限定 ID,并且调用将格式不正确,或者在关联的命名空间内进行查找时会找到更好的匹配,并考虑在所有命名空间中引入外部链接的所有函数声明翻译单元,而不是仅仅考虑在模板定义和模板实例化上下文中找到的那些声明,那么程序就会有未定义的行为。
\n
不合格的查找Serialize是在模板定义上下文中执行的,并且不会找到Serialize(int &),并且没有针对类型 的参数的 ADL int&,因此10正确的输出也是如此。
| 归档时间: |
|
| 查看次数: |
500 次 |
| 最近记录: |