Не существует безопасного или стандартного способа получить желаемый эффект, и если вы достигнете точки, когда это начинает выглядеть как жизнеспособный вариант, я настоятельно рекомендую пересмотреть ваш дизайн. Однако, если вы настойчивы, у вас есть компилятор 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;