'using declval with reference types
I would like to understand how the assignment of int & to double below in conjunction with declval works? Is T deduced to something other than 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?
}
Solution 1:[1]
Is T deduced to something other than
int &?
T will still be deduced as int&, so std::declval<T>() = std::declval<U>() will be roughly equivalent to
int& f();
double&& g();
f() = g(); // assignment
Note that f() = g() is still well-formed because f() returns a reference to an already created int that can be assigned to a double. But if you do int& f() { return 23.4; }, then you will get a compile error because non-const lvalue references cannot be initialized by a rvalue. Instead, you can create a helper function which take T as its parameter type
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 {};
This will make static_assert(initialize<int &, double>::value) fail because int& cannot be rvalue-initialized.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
