Ответ 1
В этих чертах и T
не является ссылочным типом lvalue, T
подразумевает rvalue.
Со многими пользовательскими типами T
вполне разумно назначать типы rvalue. И это даже очень полезно в некоторых контекстах:
std::vector<bool> v(5);
v[0] = true;
В приведенном выше выражении v[0]
является значением r, которому присваивается значение. И если vector<bool>
- плохой пример, то следующий новый код С++ 11 делает то же самое:
#include <tuple>
std::tuple<int, int>
do_something();
int
main()
{
int i, j;
std::tie(i, j) = do_something();
}
Выше, результат do_something()
присваивается rvalue std::tuple
. Присвоение значений r полезно и даже обычно, хотя и не выполнено в подавляющем большинстве применений присвоения.
Итак, std::is_assignable
позволяет определить различие между возможностью присвоения значения r и lvalue. Если вам нужно знать разницу, std::is_assignable
может выполнить вашу работу.
Если вы имеете дело с более распространенным случаем, например, просто пытаетесь выяснить, является ли тип T
назначаемой копией или нет, используйте is_copy_assignable<T>
. Эта черта буквально определяется в терминах is_assignable
и заставляет lhs к lvalue:
is_copy_assignable<T> == is_assignable<T&, const T&>
Итак, std::is_copy_assignable<int>::value
будет истинным, как ожидалось.
Используйте is_copy_assignable
как ваш первый выбор, или is_move_assignable
, если вам это нужно. Только тогда, когда эти черты не сработают для вас (возможно, потому, что вам нужно посмотреть на гетерогенное назначение), следует ли вернуться к использованию is_assignable
напрямую. И тогда вам нужно решить вопрос о том, хотите ли вы разрешить rvalues на lhs, чтобы учитывать случаи, которые могут включать в себя vector<bool>::reference
или tuple
ссылок. Вам нужно будет явно указать, хотите ли вы разрешить такие случаи в вашем запросе is_assignable.
Например:
#include <type_traits>
#include <vector>
int
main()
{
static_assert(std::is_assignable<std::vector<bool>::reference&, bool>(),
"Should be able to assign a bool to an lvalue vector<bool>::reference");
static_assert(std::is_assignable<std::vector<bool>::reference, bool>(),
"Should be able to assign a bool to an rvalue vector<bool>::reference");
static_assert(std::is_assignable<bool&, std::vector<bool>::reference>(),
"Should be able to assign a vector<bool>::reference to an lvalue bool");
static_assert(!std::is_assignable<bool, std::vector<bool>::reference>(),
"Should not be able to assign a vector<bool>::reference to an rvalue bool");
}