将 declval 与引用类型一起使用
using declval with reference types
我想了解下面将 int &
赋值给 double
以及 declval
是如何工作的? T
是否推导出 int &
以外的东西?
#include <iostream>
#include <type_traits>
#include <utility>
template <typename T, typename U, typename = void>
struct assignment : std::false_type{};
template <typename T, typename U>
struct assignment<T, U, std::void_t<decltype(std::declval<T>() = std::declval<U>())>> : std::true_type {};
int main() {
// int &x = 23.4; // does not compile since x is not a const ref
static_assert(assignment<int &, double>::value); // why is this OK?
}
Is T deduced to something other than int &
?
T会仍然推导为int&
,所以std::declval<T>() = std::declval<U>()
会大致等价于
int& f();
double&& g();
f() = g(); // assignment
请注意,f() = g()
仍然是 well-formed,因为 f()
returns 是对已创建的 int
的引用,可以 分配 到 double
。但是如果你这样做 int& f() { return 23.4; }
,那么你会得到一个编译错误,因为非 const
左值引用不能被右值 初始化。相反,您可以创建一个将 T
作为其参数类型
的辅助函数
template <typename T, typename U, typename = void>
struct initialize : std::false_type{};
template<typename T>
void accepted(T);
template <typename T, typename U>
struct initialize<T, U,
std::void_t<decltype(accepted<T>(std::declval<U>()))>> : std::true_type {};
这将使 static_assert(initialize<int &, double>::value)
失败,因为 int&
不能是 rvalue-initialized。
我想了解下面将 int &
赋值给 double
以及 declval
是如何工作的? T
是否推导出 int &
以外的东西?
#include <iostream>
#include <type_traits>
#include <utility>
template <typename T, typename U, typename = void>
struct assignment : std::false_type{};
template <typename T, typename U>
struct assignment<T, U, std::void_t<decltype(std::declval<T>() = std::declval<U>())>> : std::true_type {};
int main() {
// int &x = 23.4; // does not compile since x is not a const ref
static_assert(assignment<int &, double>::value); // why is this OK?
}
Is T deduced to something other than
int &
?
T会仍然推导为int&
,所以std::declval<T>() = std::declval<U>()
会大致等价于
int& f();
double&& g();
f() = g(); // assignment
请注意,f() = g()
仍然是 well-formed,因为 f()
returns 是对已创建的 int
的引用,可以 分配 到 double
。但是如果你这样做 int& f() { return 23.4; }
,那么你会得到一个编译错误,因为非 const
左值引用不能被右值 初始化。相反,您可以创建一个将 T
作为其参数类型
template <typename T, typename U, typename = void>
struct initialize : std::false_type{};
template<typename T>
void accepted(T);
template <typename T, typename U>
struct initialize<T, U,
std::void_t<decltype(accepted<T>(std::declval<U>()))>> : std::true_type {};
这将使 static_assert(initialize<int &, double>::value)
失败,因为 int&
不能是 rvalue-initialized。