2015-03-10 5 views
0

Единственный способ, которым я могу его скомпилировать, не выставляя предупреждение ни о каком члене a, когда T==B и т. Д. Для T==A равно reinterpret_cast в пределах блоков if и доступа к не- поделились с помощью указателя. Нет ли способа обойти это или намекнуть на компилятор в противном случае?C++ template struct 'не имеет имени с именем' error

Это GCC 4.8.x

enum Type { A, B}; 

template<Type T> struct S { }; 
template<> struct S<A> { int x; int a; }; 
template<> struct S<B> { int y; int x; int b; }; 

template<Type T> static void foo(int x) 
{ 
    // lots of code 

    S<T> s; 
    s.x = someCall(); 

    if (T == A) 
    { 
     s.a = 1; 
    } 
    else if (T == B) 
    { 
     s.y = 2; 
     s.b = 3; 
    } 

    // a bunch of common code 
} 

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

ответ

1

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

template <Type T> void bar(S<T>&); 

template <> void bar(S<A>& s) {s.a = 1;} 
template <> void bar(S<B>& s) {s.y = 2; s.b = 3;} 

template<Type T> static void foo(int x) 
{ 
    // lots of code 

    S<T> s; 
    s.x = someCall(); 

    bar(s); 

    // a bunch of common code 
} 
+0

Я знаю об этом, я надеялся избавиться от кода плиты котла, если это возможно ... – stgtscc

+1

Я думаю, что это _does_ устранит как можно больше плитки. Весь распространенный код хранится в шаблоне 'foo()', специфика в специальном 'bar''s – haavee

+0

Интересно, если' std :: enable_if' или даже lambas? Слишком плохо, что компилятор обрабатывает код внутри if-statement как ошибку, очевидно, что пути, которые вызывают ошибку, оптимизированы в конце ... – stgtscc

0
if (T == A) 
[...] 
else if (T == B) 
[...] 

A, B и T здесь время компиляции сущности, не во время выполнения объектов. И все же вы пытаетесь выполнить оценку времени во время выполнения во время компиляции. Теперь, конечно, вы могли бы попытаться взломать что-то с помощью своего рода iffy cast (попробуйте и проиграть) или попробуете какой-нибудь другой kludgery, но код говорит вам: вы делаете это неправильно.

Специализируется foo является одним из способов, так как может быть levarging SFINAE (как с enable_if), но из того, что мало я вижу здесь вашего прецедента, это тоже будет неправильно. Это потому, что код, который вы пытаетесь реализовать, - это какой-то код инициализации или код, который управляет внутренним состоянием используемого объекта. В некотором смысле вы нарушаете принцип единоличной ответственности.

Так переместите этот код туда, где несет ответственность: в классе, который находится init ed.

template<> struct S<A> { int x; int a; void init() {a=1;} }; 
template<> struct S<B> { int y; int x; int b; void init() { x=2; y=3; } }; 

template<Type T> static void foo(int x) 
{ 
    // lots of code 

    S<T> s; 
    s.x = someCall(); 

    s.init(); 

    // a bunch of common code 
} 

Вы также можете использовать заводской класс. Это абстрагировало бы как создание объекта, так и вызов init(), который может принимать разные параметры в зависимости от конечного типа.

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