Как убедиться, что параметр шаблона не является постоянным и не является ссылочным

#c #c -concepts

Вопрос:

Часто (большую часть времени?) при создании типов с параметрами типа шаблона вы хотите убедиться, что параметр типа заполнен без ссылки, неквалифицированным (неконстантным, энергонезависимым) типом. Однако простое определение, подобное приведенному ниже, позволяет пользователю вводить любой тип для T :

 template <typename T>
class MyContainer {
    T* whatever;
    T moreStuff;
};
 

В современном C есть концепции, которые должны быть способны решить эту проблему. Каков наилучший (и желательно наименее шаблонный) способ сделать это?

Ответ №1:

static_assert это хороший вариант:

 #include <type_traits>

template <typename T>
class MyContainer
{
    static_assert(!std::is_reference_v<T>);
    static_assert(!std::is_const_v<T>);
    static_assert(!std::is_volatile_v<T>);

    T* whatever;
    T moreStuff;
};
 

Ответ №2:

Я бы использовал для этого концепцию.

 template <typename T>
concept cvref_unqualified = std::is_same_v<std::remove_cvref_t<T>, T>;
 
 template <cvref_unqualified T>
class MyContainer {...};
 

Комментарии:

1. Хотя для меня концепция должна иметь «значение». Особенно когда мы имеем в виду правила подчинения.

2. @Jarod42, возможно, стандартные концепции имеют ту же проблему, например derived_from . Но да, ОП мог бы обернуть эту концепцию чем-то вроде concept MyContainerElement

3. Здесь мы также имеем композицию из нескольких черт, которая не отражена в концепции. и следует провести размышление (OP, в зависимости от потребностей), чтобы узнать, следует ли разделять эту концепцию или не допускать ее включения.

Ответ №3:

Вы можете проверить тип с помощью static_assert like

 template <typename T>
class MyContainer {
    static_assert(std::is_same_v<std::remove_cv_t<std::remove_reference_t<T>>, T>, "T must be non-reference, unqualified type");
    T* whatever;
    T moreStuff;
};