Прежде всего, я прошу прощения за смутное название этого вопроса. Я не был уверен, как подвести итог.
То, чего я хочу достичь, это следующее: я хочу иметь возможность передавать параметры не типового шаблона разных типов в один и тот же шаблон класса, что приводит к различным экземплярам. Что-то вроде этого:
Foo<1>();
Foo<'1'>(); // different types of object
Я не думаю, что это возможно, поэтому я вынужден сделать что-то подобное
template <typename T, T Val>
struct Foo;
template <int Val>
struct Foo<int, Val>
{};
template <char Val>
struct Foo<char, Val>
{};
//...
Foo<int, 1>();
Foo<char, '1'>();
такой, что Foo
может быть специализированным на основе первого параметра шаблона. Однако это усложняет синтаксис мини-языка, который я пытаюсь реализовать в моей структуре метапрограммирования. Есть ли какая-либо техника, которая позволяет мне различать Foo<1>
от Foo<'1'>
? По сути, я хочу установить флаг времени компиляции (в перечислении), чтобы указать, int
или же char
был пропущен, без явного указания их.
РЕДАКТИРОВАТЬ
Ответы заставили меня понять, что мой вопрос подразумевает, что мне действительно нужны экземпляры этих объектов (во время компиляции). Я не…
Скажите, что каким-то образом стандарт позволил бы мне перегрузить шаблон класса так, чтобы Foo<1>
а также Foo<'1'>
разные типы, и содержат разные значения для их flag
поле. Эти типы могут затем сами быть переданы в другой шаблон класса, который может проверять их и делать с ними интересные вещи, например:
template <typename FooType>
struct Bar
{
typedef typename If < FooType::flag, int, char >::Type Type;
};
Это все очень легко сделать, когда вы ничего не имеете против явной передачи типа, но это кажется излишним …
Вы можете использовать макрос:
#define MAKE_FOO(value) \
Foo<decltype(value), value>()
На самом деле, я думаю, что вам нужно что-то вроде широко распространенного шаблона функции make_something
во время компиляции. К сожалению, я не знаю, как это реализовать.
Если вам просто нужны значения, доступные во время компиляции, но на самом деле они не нужны как часть типа (например, если вам не нужно Foo<int, 1>
а также Foo<int, 2>
быть разными типами), то вы можете использовать constexpr
конструктор вместе с constexpr
функция, чтобы вызвать Foo
экземпляры во время компиляции.
#define DECLTYPE_AUTO(expr) \
-> decltype(expr) { return expr; }
template <typename T>
struct Foo {
constexpr Foo(T t) : value(t) {}
T value;
}; // Foo
template <typename T>
constexpr auto MakeFoo(T val)
DECLTYPE_AUTO(Foo<T>(val));
static_assert(MakeFoo(2).value == 2, "");
static_assert(MakeFoo('1').value == '1', "");
int main() {}
Вы могли бы сделать что-то вроде этого:
template <int Val>
struct Foo<int, Val>
{
static MyEnum tag = myTag1;
};template <char Val>
struct Foo<char, Val>
{
static MyEnum tag = myTag2;
};