Шаблоны и предварительная обработка в С++

Вопрос:

Как кто-то может скомпилировать этот код:

#include <iostream>
using namespace std;

enum E { A, B};

template< E x>
class C {
public:
#if( x == A)
static void foo() {
cout << "A";
}
#elif( x == B)
static void goo() {
cout << "B";
}
#endif
};


int main() {
C< A>::foo();
C< B>::goo();

return 0;
}

error: ‘goo is not a member of ‘C<(E)1u>

У меня есть два больших класса, которые отличаются только несколькими строками, поэтому я хотел создать шаблон enum. Проблема в том, что эти строки using в них ключевое слово, поэтому я не знаю, что там положить.

Есть ли правильный способ сделать это?

PS> Мне нужно использовать С++ 03.

РЕДАКТИРОВАТЬ: Немного разъяснений. Я знаю о template<> построения, но я не хотел его использовать, потому что у меня было много дублирования кода. Может быть, я каким-то образом сделаю частичное “создание шаблона” (если это правильный термин для template<>)?

Предположим, у меня есть два класса (и у меня их не будет больше):

class A {
public:
//…a lot of code…
//few lines that differs in A and B
}

class B {
//…the same mass of code…
//few lines that differs in A and B
}

Поэтому я решил создать шаблон для enum:

enum E { A, B}
template< E>
class C{
//…common code…
}

Теперь я не знаю, что делать с этими несколькими строками, которые отличаются в и B. Я знаю, что общий способ заключается в создании шаблона instanciation, но тогда я получу именно то, что у меня было с классами A и B

Из точки ООП следует использовать общую Base для A и B Но проблема в том, что A и B уже совпадают. Они отличаются только строкой:

using CanStoreKeyValue< QString, Request>::set;
using CanStoreKeyValue< QString, Response>::set;

где Response and Request – typedefs. Более того, в моем коде A и B есть дочерние элементы одного и того же шаблонного абстрактного класса. И, конечно, они наследуют его с помощью другого шаблона. Это как-то обманывает использование шаблона enum – компилятор просто не может видеть, что некоторые виртуальные методы более не чисты. Итак… почему я спрашиваю, о чем я прошу. Я думал, что препроцессор может взаимодействовать с движком шаблонов с #if -directives (в конце они оба являются процессами компиляции).

Лучший ответ:

Если вы не хотите специализации, я полагаю, что ограничение функций с помощью SFINAE является вариантом (Live at coliru):

template <E x>
class C {
public:
    template <E y = x>
    static typename std::enable_if<y == A>::type foo() {
        cout << "A";
    }

    template <E y = x>
    static typename std::enable_if<y == B>::type goo() {
        cout << "B";
    }
};

Но если дублирование кода является вашей единственной проблемой, используйте специализацию и поместите общий код в базовый класс (Live at Coliru), это немного чище:

class C_base {};

template <E x>
class C : public C_base {};

template <>
class C<A> : public C_base {
public:
    static void foo() {
        cout << "A";
    }
};

template <>
class C<B> : public C_base {
public:
    static void goo() {
        cout << "B";
    }
};

Ответ №1

Вы не можете использовать препроцессор для достижения того, что вы пытаетесь сделать. Вам нужна специализированная специализация:

enum E { A, B};

template< E x>
class C;

template <>
class C<A> {
public:
static void foo() {
cout << "A";
}
};

template <>
class C<B> {
public:
static void goo() {
cout << "B";
}
};

Ваша обновленная проблема по-прежнему может быть решена специализацией шаблона:

enum E { A, B };

template< E x >
struct CanStoreKeyValueHelper;

template<>
struct CanStoreKeyValueHelper<A> {
typedef CanStoreKeyValue< QString, Request>::set type;
};

template<>
struct CanStoreKeyValueHelper<B> {
typedef CanStoreKeyValue< QString, Response>::set type;
};

template< E x>
class SuperPuperBigClass {
public:
typedef typename CanStoreKeyValueHelper<x>::type set;
...
};

Но неясно, почему вы не делаете это так просто:

template<class T>
class SuperPuperBigClass {
public:
typedef typename CanStoreKeyValue<QString, T>::set set;
};

и создать экземпляр с типом запроса и ответа

Оцените статью
TechArks.Ru
Добавить комментарий