псевдоним параметра шаблона без типа в другом типе - PullRequest
0 голосов
/ 05 мая 2020

Я пытаюсь определить общий c контейнер с параметром шаблона. Для параметра шаблона можно выбрать предопределенные значения. Для удобства я хотел бы также разрешить передачу целочисленных значений в качестве альтернативы и автоматически сопоставить их с соответствующим предопределенным значением.

Например (это не работает):

struct Option {
    Option(unsigned int);
};

static Option A(1);
static Option B(2);

template<Option& o>
class Value {};

Value<B> b;
Value<2> c;  // <-- this is not permitted

(бонусный вопрос: та же проблема, но альтернативным значением является тип, например: uint8_t -> 1, uint32_t -> 2)

1 Ответ

2 голосов
/ 06 мая 2020

Не существует безопасного или стандартного способа получить желаемый эффект, и если вы достигнете точки, когда это начинает выглядеть как жизнеспособный вариант, я настоятельно рекомендую пересмотреть ваш дизайн. Однако, если вы настойчивы, у вас есть компилятор c ++ 17 и вы готовы использовать указатели вместо ссылок, вы можете использовать вывод параметров шаблона без типа с помощью SFINAE, чтобы получить желаемый эффект:

#include<type_traits>

struct Option{
    Option(unsigned int);
}

static Option A(1);
static Option A(2);

//enable this template if the non-type template parameter is a pointer-to-Option, 
//    or an unsigned int can be constructed from the parameter
template<auto I, typename=std::enable_if_t<
                          std::is_same_v<decltype(I), Option*> ||
                          std::is_constructible_v<uint, decltype(I)>
                                          >>
class Value{

};

Value<&B> b;
Value<2> c; 

Это будет работать, и довольно просто добавить поддержку для большего количества типов. Однако использование параметра шаблона нетривиально и потребует решения, зависящего от того, как вы планируете использовать параметр шаблона.

На основе приведенного выше кода я бы подумал об использовании вместо этого классов перечисления, что может предоставить гораздо более подходящую альтернативу:

enum class Option{
    A=1,B=2
};

template<Option o>
class Value{
};

Value<Option::B> b;
Value<static_cast<Option>(2)> c; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...