支撑函数转换为引用类型,标准中的漏洞或编译器错误?
Braced functional cast to reference type, a hole in the standard or compilers bug?
根据标准,花括号函数转换总是产生纯右值,[expr.cast]/2
Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized with the initializer.
当指定类型是引用类型时很难解释,因为它可能发生在泛型编程中。编译器在这种情况下采用了特定的行为:
#include <type_traits>
struct A {
A ()=default;
A (const A&);
};
template <class T, class U>
decltype(auto)
f(U& a) {
static_assert (std::is_same_v <decltype (T{a}), T>);
return T{a};
}
#if defined(__clang__) || defined(_MSC_VER)
void g1(A a){
decltype(auto) v = f<A&>(a); //GCC: error try to bind a prvalue to a non-const lvalue
static_assert (std::is_same_v <decltype(v), A&>);
}
#endif
void g2(A a){
decltype(auto) v = f<const A&>(a); //GCC: call the copy constructor of A
//MSVC and Clang: a no op (direct reference binding)
static_assert (std::is_same_v <decltype(v), const A&>);
}
对于 Clang,GCC 和 MSVC 同意 decltype(T{a})
其中 T is A&
是 A&
类型这一事实。这意味着根据 decltype 规范,结果不是纯右值。所以看起来 none 这些编译器符合标准。
T{a}
对Clang和MSVC的评估只是直接引用绑定。
GCC 拒绝编译 g1
。表达式 T{a}
构造了 a
的副本,然后暂时将临时绑定到 T{a}
的结果(这可以在模板 h [=21 的显式实例化的汇编中看到) =]).
在这种情况下有编译器吗?还是只是 "no diagnostic required" 个案例?
这是CWG1521:
T{expr}
with reference types
According to 8.2.3 [expr.type.conv] paragraph 4,
Similarly, a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type direct-list-initialized (11.6.4 [dcl.init.list]) with the specified braced-init-list, and its value is that temporary object as a prvalue.
这个措辞不处理 T
是引用类型的情况:不可能创建该类型的临时对象,并且可能结果是一个 xvalue,而不是 prvalue。
根据标准,花括号函数转换总是产生纯右值,[expr.cast]/2
Otherwise, the expression is a prvalue of the specified type whose result object is direct-initialized with the initializer.
当指定类型是引用类型时很难解释,因为它可能发生在泛型编程中。编译器在这种情况下采用了特定的行为:
#include <type_traits>
struct A {
A ()=default;
A (const A&);
};
template <class T, class U>
decltype(auto)
f(U& a) {
static_assert (std::is_same_v <decltype (T{a}), T>);
return T{a};
}
#if defined(__clang__) || defined(_MSC_VER)
void g1(A a){
decltype(auto) v = f<A&>(a); //GCC: error try to bind a prvalue to a non-const lvalue
static_assert (std::is_same_v <decltype(v), A&>);
}
#endif
void g2(A a){
decltype(auto) v = f<const A&>(a); //GCC: call the copy constructor of A
//MSVC and Clang: a no op (direct reference binding)
static_assert (std::is_same_v <decltype(v), const A&>);
}
对于 Clang,GCC 和 MSVC 同意 decltype(T{a})
其中 T is A&
是 A&
类型这一事实。这意味着根据 decltype 规范,结果不是纯右值。所以看起来 none 这些编译器符合标准。
T{a}
对Clang和MSVC的评估只是直接引用绑定。
GCC 拒绝编译 g1
。表达式 T{a}
构造了 a
的副本,然后暂时将临时绑定到 T{a}
的结果(这可以在模板 h [=21 的显式实例化的汇编中看到) =]).
在这种情况下有编译器吗?还是只是 "no diagnostic required" 个案例?
这是CWG1521:
T{expr}
with reference typesAccording to 8.2.3 [expr.type.conv] paragraph 4,
Similarly, a simple-type-specifier or typename-specifier followed by a braced-init-list creates a temporary object of the specified type direct-list-initialized (11.6.4 [dcl.init.list]) with the specified braced-init-list, and its value is that temporary object as a prvalue.
这个措辞不处理
T
是引用类型的情况:不可能创建该类型的临时对象,并且可能结果是一个 xvalue,而不是 prvalue。