C++ 有人能给我解释一下下面的模板代码吗?
我是模板编程新手,我打算使用这里的解决方案来确保使用的类型定义了运算符。但是我想理解这个代码。我查阅了CPPPreference的信息,但我更不清楚它是如何工作的 不幸的是,它对我来说是相当神秘的,我想它会询问代码中某些内容的含义和原因C++ 有人能给我解释一下下面的模板代码吗?,c++,templates,C++,Templates,我是模板编程新手,我打算使用这里的解决方案来确保使用的类型定义了运算符。但是我想理解这个代码。我查阅了CPPPreference的信息,但我更不清楚它是如何工作的 不幸的是,它对我来说是相当神秘的,我想它会询问代码中某些内容的含义和原因 namespace CHECK { struct No {}; template <typename T, typename Arg> No operator==(const T&, const Arg&);
namespace CHECK
{
struct No {};
template <typename T, typename Arg>
No operator==(const T&, const Arg&);
/* Why are there two definitions of structures? Is this needed at all? Is
* there a simpler version of this whole code snippet?
*/
template <typename T, typename Arg = T>
struct EqualExists {
/* Why does this have to be a enum? What effect does this have? */
enum {
/* What happens if == sign is not defined for T? What would the
* below comparison return when true/false? (The comparison *(T*)(0) == *(Arg*)(0))
*
* What is the need for No here? Why is it needed and how will
* comparing it with the return type of == comparison be true ever?
* How can the return type of == comparison and No structure be the same?
*/
value = !std::is_same<decltype(*(T*)(0) == *(Arg*)(0)), No>::value
};
};
}
名称空间检查
{
结构号{};
模板
无运算符==(常数T&,常数Arg&);
/*为什么有两种结构的定义?需要吗?需要吗
*整个代码段有没有更简单的版本?
*/
模板
结构均衡论者{
/*为什么必须是枚举?这有什么影响*/
枚举{
/*如果没有为T定义==符号,会发生什么情况
*当为真/假时,下面的比较返回值?(比较*(T*)(0)=*(Arg*)(0))
*
*什么是不需要这里?为什么需要它和如何将
*将其与返回类型==比较是否为真?
*==比较和无结构的返回类型如何相同?
*/
value=!std::值是否相同::值
};
};
}
有人能把这和原来的问题联系起来吗?希望这也能帮助cpp新手理解这一点。解释
让我们一步一步地把它分解:
:假设地址0处有一个(T*)(0)
类型的对象;此子表达式的类型是指针T
:假设地址0处有一个*(T*)(0)
类型的对象;此子表达式的类型是引用,因为前面的星号取消了对指针的引用。它看起来有点像一个空指针解引用,但稍后会详细介绍T
:假设地址0处有一个*(Arg*)(0)
类型的对象;与T相同的模式Arg
:这相当于调用*(T*)(0)==*(Arg*)(0)
,具有额外的方便性。操作符==(*(T*)(0),*(Arg*)(0))
- 如果用户定义的
不存在,则将匹配运算符==
命名空间运算符。这是一个“全面”的模板检查
- 如果用户定义的
:decltype(*(T*)(0)==*(Arg*)(0))
说。在这种情况下,类型是decltype
调用的返回类型。操作符==
- 实际上不会发生比较操作,也不会解除对内存的限制
:'sstd::is_same::value
如果类型相同,则为value
,否则为true
。false
是一个静态constexpr bool::value
- 这两个类型参数是
和structdecltype(…)
CHECK::No
- 真实世界的
通常返回bool。有时它可能返回用户定义的类型。不太可能有人会编写自定义的操作符==
来返回操作符==
,而此代码依赖于该假设检查::No
<>代码>枚举值> .STD::ISHYNE::值} /COD>:枚举总是编译时常数,适用于旧的C++编译器和规范(如C++ 03,其中代码> COSTEXPRO< /CODE >不存在),与<代码> CONTXPRP</代码>兼容,不需要存储。
static constexpr bool value=!std::is_same::value代码>将是等效的
- 从技术上讲,取消对空指针的引用是非法的;这是一个安全的选择
- 从技术上讲,有人可以编写
,这会使CHECK误认为运算符未定义CHECK::No operator==(const Foo&,const Bar&)
- 检查命名空间中的
可能会对全局定义的运算符==定义产生阴影,从而导致误判运算符==
template <typename T, typename Arg = T>
class EqualExists {
template <class U = T, class V = Arg, bool Exists = !!sizeof(std::declval<U>() == std::declval<V>())>
static std::true_type Func(const T&, const Arg&);
template <class U, class V>
static std::false_type Func(const U&, const V&);
public:
static constexpr bool value = decltype(Func(std::declval<T>(), std::declval<Arg>()))::value;
};
模板
阶级平等主义者{
模板
静态std::true_type Func(常量T&,常量Arg&);
模板
静态std::false_类型Func(常量U&,常量V&);
公众:
静态constexpr bool value=decltype(Func(std::declval(),std::declval())::value;
};
[编辑]我的原始答案有一个bug:在Exists计算中没有使用模板args U和V,在gcc上编译失败。(出于某种原因在msvc工作)
模板
静态std::true_type Func(常量T&,常量Arg&);
说明
让我们一步一步地把它分解:
:假设地址0处有一个(T*)(0)
类型的对象;此子表达式的类型是指针T
:假设地址0处有一个*(T*)(0)
类型的对象;此子表达式的类型是引用,因为前面的星号取消了对指针的引用。它看起来有点像一个空指针解引用,但稍后会详细介绍T
:假设地址0处有一个*(Arg*)(0)
类型的对象;与T相同的模式Arg
:这相当于调用*(T*)(0)==*(Arg*)(0)
,具有额外的方便性。操作符==(*(T*)(0),*(Arg*)(0))
- 如果用户定义的
不存在,则将匹配运算符==
命名空间运算符。这是一个“全面”的模板检查
- 如果用户定义的
:decltype(*(T*)(0)==*(Arg*)(0))
说。在这种情况下,类型是decltype
调用的返回类型。操作符==
- 实际上没有发生比较操作,n
template <class U, class V, bool Exists = !!sizeof(std::declval<T>() == std::declval<Arg>())> static std::true_type Func(const T&, const Arg&);
- 实际上没有发生比较操作,n