2016-03-16 3 views
1

Мне нужна помощь здесь. Я новичок в метапрограммировании, поэтому я даже не знаю, где искать решение (которое пока не представляется возможным).Частичная специализация non type аргумент

template<typename T, void(*FuncPtr_A)(int), int(*FuncPtr_B)() = nullptr> 
class DummyClass 
{ }; 

template<typename T, int(*FuncPtr_B)()> 
class DummyClass<T, nullptr, FuncPtr_B> 
{ }; 

void FUNC_A(int) { } 
int FUNC_B() { return 0; } 

int main() 
{ 
    DummyClass <int, FUNC_A, FUNC_B> test1; // works 
    DummyClass <int, FUNC_A> test2;   // works 
    DummyClass <int, FUNC_B> test3;   // error: is there any way to make this work? 
    return 0; 
} 
+1

Фабричные методы? – skypjack

+0

Я уже знаю, как это сделать. Я новичок в мета-программировании, а не новичок на C++. Я просто хочу знать, возможно ли что-то, близкое к тому, что я пытаюсь сделать, или, по крайней мере, подтвердить, что это невозможно, и нет никакого способа обойти это. – James

+0

Ваша специализация не специализируется на btw, что вы, кажется, хотите, это своего рода псевдоним. – Jarod42

ответ

2

Лучшее, что я мог сделать, это:

namespace detail { 
    template<typename T, void(*FuncPtr_A)(int), int(*FuncPtr_B)()> 
    class DummyClass 
    { }; 
} 

template<class T, void(*FuncPtr_A)(int)> 
auto DummyClass() 
{ 
    return detail::DummyClass<T, FuncPtr_A, nullptr>(); 
} 

template<class T, int(*FuncPtr_B)(void)> 
auto DummyClass() 
{ 
    return detail::DummyClass<T, nullptr, FuncPtr_B>(); 
} 

template<class T, void(*FuncPtr_A)(int), int(*FuncPtr_B)(void)> 
auto DummyClass() 
{ 
    return detail::DummyClass<T, FuncPtr_A, FuncPtr_B>(); 
} 




void FUNC_A(int) { } 
int FUNC_B() { return 0; } 

int main() 
{ 
    auto test1 = DummyClass <int, FUNC_A, FUNC_B>(); // works 
    auto test2 = DummyClass <int, FUNC_A>();   // works 
    auto test3 = DummyClass <int, FUNC_B>();   // works 
    return 0; 
} 

EDIT:

Если вам нужно имя типа (например, для использования в качестве элемента данных в классе):

int main() 
{ 
    decltype(DummyClass <int, FUNC_A, FUNC_B>()) test1 {}; // works 
    decltype(DummyClass <int, FUNC_A>()) test2 {};   // works 
    decltype(DummyClass <int, FUNC_B>()) test3 {};   // works 
    return 0; 
} 
+1

Это недопустимо C++ 11. – jotik

+0

@jotik действительно? он компилируется при применении clang с флагом -std = C++ 1z –

+0

@jotik: он действителен C++ 14, для C++ 11 вы должны указать тип вместо 'auto' return type. – Jarod42

0

Это не может быть сделано в C++ 11 (или C++ 14) с использованием синтаксиса в исходном вопросе, потому что

  1. вы можете только по умолчанию аргументов шаблона в конце из списка параметров шаблона, и
  2. вы не можете иметь параметр шаблона не типа принимает значение аргументов различных типов, если они не могут быть конвертированы в тип параметра непигового шаблона в соответствии с правилами правил преобразования в C++ 11 §14.3.2.5.

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

Также обратите внимание, что 1. аналогичным образом выполняется для аргументов по умолчанию по умолчанию, однако для функций, которые вы можете обойти проблему, путем предоставления перегрузок на основе типов аргументов, что является трюком, на котором обходной путь фабричного шаблона, предложенный Комментарий skypjack к вопросу и RichardHodges answer основывается на.

+0

Я предполагаю, что все держится на C++ 14? Я обновил свой тег, извиняюсь за то, что он ошибался в первую очередь. – James

+0

Думаю, да, да. – jotik

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