【发布时间】:2016-10-28 14:20:17
【问题描述】:
我在std::optional 实现中遇到了这段代码:
template <class T, class U>
struct is_assignable
{
template <class X, class Y>
constexpr static bool has_assign(...) { return false; }
template <class X, class Y, size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true)) >
// the comma operator is necessary for the cases where operator= returns void
constexpr static bool has_assign(bool) { return true; }
constexpr static bool value = has_assign<T, U>(true);
};
我无法理解它是如何工作或如何评估它的部分是size_t S = sizeof((std::declval<X>() = std::declval<Y>(), true)) 我知道如果分配操作失败,它将回退到返回 false 的 has_assign 的第一个定义,但我不知道为什么它有 , true) 部分。
我对在分配运算符上返回 void 的结构进行了一些测试,并删除了 sizeof 中的 , true 部分给了我相同的结果。
【问题讨论】:
-
en.cppreference.com/w/cpp/language/sfinae 。如果
sizeof中的表达式对给定的X和Y有效,则has_assign有两个重载,而has_assign<T, U>(true)则选择第二个重载作为更好的匹配。如果表达式无意义,则丢弃该重载,并选择第一个。 -
一些编译器将
sizeof(void) == 1定义为扩展。启用更多警告。 -
写
class S = decltype(std::declval<X>() = std::declval<Y>())会更直接。我们不管S是什么,只要那个表达式是有效的。 -
@SamVashavchik 我理解这个问题的方式,它不是关于 SFINAE。 OP 甚至说“我知道如果分配操作失败,它将回退到返回 false 的 has_assign 的第一个定义......”真正的问题是为什么使用逗号运算符 (
, true),它几乎没有与 SFINAE 本身有关。 -
@Fanael 没有。仔细看看
sizeof里面的内容。这是sizeof(something=something, true)。我想如果我让X::operator=(Y)返回一个重载operator,()的类,它可能会被破坏。
标签: c++