C++ 模板 - 完整指南:了解有关 decltype 和 return 类型的脚注注释

C++ Templates - The Complete Guide: Understanding footnote comment about decltype and return type

第 2 版 C++ 模板 - 完整指南 在第 435 页包含以下代码

#include <string>
#include <type_traits>

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

template<typename T>
struct HasBeginT<T, std::void_t<decltype(std::declval<T>().begin())>>
    : std::true_type {};

并评论说 decltype(std::declval<T>().begin()) 用于测试在 T 上调用 .begin() 是否有效。

这一切都有道理,我认为...

令我震惊的是脚注中的评论:

Except that decltype(<i>call-expression</i>) does not require a nonreference, non-void return type to be complete, unlike call expressions in other contexts. Using decltype(std::declval<T>().begin(), 0) instead does add the requirement that the return type of the call is complete, because the returned value is no longer the result of the decltype operand.

不是很懂

为了尝试使用它,我尝试使用以下代码 void 成员 begin 查看它的行为

struct A {
    void begin() const;
};

struct B {
};

static_assert(HasBeginT<A>::value, "");
static_assert(!HasBeginT<B>::value, "");

但是无论有没有 , 0.

,这两个断言都通过了

您的演示使用 void begin() const; 来测试以下内容

... instead does add the requirement that the return type of the call is complete ...

但是 void return 类型与不完整的 return 类型不同。为此你可以试试

struct X;

struct A {
    X begin() const;
};

这里,X确实不完整,现在, 0很重要。有了它,第一个 static_assert 不会通过,但是没有 , 0.

它会通过

demo