Подтвердить что ты не робот

Использовать случаи для std:: add_const и аналогичных

Некоторые преобразования типов в <type_traits> также могут быть выражены с использованием синтаксиса основного языка (например, std::add_const<T>::type is/кажется эквивалентным const T). Dtto для std::add_lvalue_reference и, возможно, других. Какая польза от этих черт типа?

Я полностью понимаю, что стандарт будет предоставлять "неполный набор инструментов" без них, и я могу представить себе мета-путь, примерно так:

template<typename In, template <typename> class Modifier>
struct Apply {
  typedef typename Modifier<T>::type Out;
};

Apply<int, std::add_const>

Существуют ли какие-либо другие варианты использования этих признаков, которые могут быть выражены синтаксически, или они просто включены "из чувства полноты" и для случайного мета-использования?

4b9b3361

Ответ 1

Эти черты исходят от Boost и предложения о добавлении их в стандарт, N1345, цитирует Андрея Александреску:

"Я понимаю аргумент симметрии для добавления add_const, add_volatile, add_cv и add_pointer, однако я бы сказал, что они устраняют их. Эквиваленты, предоставляемые языком, просто проще и приятнее".

То же предложение также дает такое обоснование:

Замечание автора: поверхностно классы add_const, add_volatile и add_cv не имеют значения, поскольку, например, add_const:: type такой же, как T const, для всех T (в настоящее время это не относится к типам функций, но issue 295). Однако опыт повышения эффективности заключается в том, что несколько пользователей попросили, чтобы эти шаблоны присутствовали в библиотеке по следующим причинам: (a) Некоторые пользователи находят их более явными - при объединении шаблонов преобразования, в частности, пользователи, такие как "встроенные" документация ", которую предоставляют эти шаблоны. (b) Не все пользователи знают, что cv-квалификация ссылки разрешена и не имеет никакого эффекта, или что cv-квалификационный тип, который уже имеет квалификацию cv, разрешен и не имеет никакого эффекта. (c) Компиляторы могут выдавать предупреждения, когда cv-квалификацию типа, который является ссылкой, или уже имеет cv-квалификатор, эти шаблоны могут быть реализованы таким образом, что эти сообщения в этих случаях подавляются.

Кроме того, для add_reference (переименовано в add_lvalue_reference в стандарте):

Примечание автора: шаблон add_reference был одним из оригинальных мотивов для библиотеки признаков типа boost. Однако разрешение вопроса 106 заставляет шаблон выглядеть в значительной степени избыточным. Несмотря на то, что add_reference может быть полезно при подавлении предупреждений компилятора, когда непреднамеренно создает ссылки на ссылки в коде шаблона.

Ответ 2

Эти черты предоставляются для случайного мета-использования. Это позволяет передавать требуемые cv-квалификаторы в метапрограммирование.

template<class T,template<class> class Trait>
struct transform
{
  /* working with T creating newT*/

  typedef Trait<newT>::type type;
};

template<class T>
struct special_transform
  : transfrom<T, std::add_const>
{};

В этом случае вы не можете заменить std::add_const на const.

Ответ 3

Единственный случай использования, который я знаю, показан ниже:

struct F
{
    bool f() const { return true; }
    bool f() { return false; }
};
assert(!F{}.f())
assert(std::add_const_t< F >{}.f());

Он также необходим для тестирования функциональности функциональных функций cv-ref-qual, которые могут различаться для разных перегрузок (только для lref-квалифицированных современных С++ имеет удобную функцию std::as_const):

struct F
{
    int g() & { return 1; }
    int g() const & { return 2; }
    int g() && { return 3; }
    int g() const && { return 4; }
};
F f;
assert(f.g() == 1);
assert(std::as_const(f).g() == 2);
assert(F{}.g() == 3);
assert(std::add_const_t< F >{}.g() == 4); // rarely needed, but if needed, then it helps

Ответ 4

add_const может использоваться для разрешения конфликтов вывода типов.

template <typename T>
class wrapper;

template <typename T>
bool operator==(wrapper<T> const& w, T const& t);

Проблемы возникают, если мы используем wrapper<T const>:

wrapper<int const> w = { 42 };
assert(w == 42); // Error: conflicting deduced types

T одновременно выводится как int, так и int const. Это можно решить, используя add_const:

template <typename T>
bool operator==(wrapper<T> const& w, add_const_t<T>& t);