2014-01-10 5 views
6

Прежде всего, я сожалею о неопределенном названии этого вопроса. Я не был уверен, как это обобщить.C++ шаблон специализации/перегрузки

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

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, без явного указания их.

EDIT Ответов я понял, что мой вопрос подразумевает, что я на самом деле нужен (во время компиляции) экземпляры этих объектов. Я не ...

Скажем, что-то стандарт позволит мне перегрузить шаблон класса таким образом, чтобы Foo<1> и Foo<'1'> различные типы и содержат различные значения для их flag поля. Эти типы могут затем сами быть переданы в другой шаблон класса, который может осмотреть их и сделать интересные вещи с ним, например:

template <typename FooType> 
struct Bar 
{ 
    typedef typename If < FooType::flag, int, char >::Type Type; 
}; 

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

+1

Да, я никогда не думал об этом. +1 –

+0

Я тоже, до тех пор, пока я не нуждался в этом ;-) – JorenHeit

+0

Это выглядит более общим случаем [моего вопроса] (http://stackoverflow.com/q/9400581/212858), чей ответ я боюсь waasn't поощряющ – Useless

ответ

2

Вы можете использовать макрос:

#define MAKE_FOO(value) \ 
    Foo<decltype(value), value>() 

На самом деле, я думаю, вам нужно что-то вроде широко распространенного шаблона функции make_something во время компиляции. К сожалению, я не знаю, как его реализовать.

+0

Я боялся, что это единственный ответ. Конечно, я уже рассматривал этот вариант, но макросы злы ;-) Отметьте как ответ, если никто не имеет лучшей идеи. – JorenHeit

+0

Что касается того же подхода, но с параметрами шаблона по умолчанию? 'template ' Но как-то я уверен, что это не скомпилируется: D – Paranaix

+1

@Paranaix это не сработает, потому что параметры по умолчанию должны быть заполнены справа. – mpark

0

Вы могли бы сделать что-то вроде этого:

template <int Val> 
struct Foo<int, Val> 
{ 
    static MyEnum tag = myTag1; 
}; 


template <char Val> 
struct Foo<char, Val> 
{ 
    static MyEnum tag = myTag2; 
}; 
+0

И цель в том, что? – Paranaix

+0

Distinguish Foo <1> от Foo <'1'>? –

+0

Вам все равно нужно передать либо 'int', либо' char' в 'Foo', чего я хочу избежать. Я хочу, чтобы компилятор выводил тип, как и при перегрузке функции. [Post] (http://stackoverflow.com/q/9400581/212858) от Useless - это точно такая же проблема, и затем было сделано заключение, что это невозможно ... – JorenHeit

1

Если вам просто нужны значения, доступные во время компиляции, но на самом деле они не нужны как часть этого типа (как и в случае, если вам не нужны Foo<int, 1> и Foo<int, 2>, чтобы быть разными), то вы можете использовать a 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() {} 
+0

Интересно ... Однако я думаю, что это не очень полезно для меня. Моя вина полностью за то, что вы не указали достаточно подробностей в вопросе. Вопрос отредактирован :-) – JorenHeit

Смежные вопросы