проверка класса в шаблонах c ++ без экземпляра класса - PullRequest
2 голосов
/ 27 июня 2011

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

Проблема в том, что функция, которая должна быть реализована, не получает ни одного экземпляра класса, поэтомуединственное, что известно, это имя класса.Так что это невозможно сделать с помощью dynamic_cast, так как он требует экземпляра объекта

template<T>
class A 
{
  void somefunction(void)
  {
     if (T instanceof Foo) then ...
     else ...
  }
}

, добавляя некоторые пояснения

class X: public Foo {};
class Y {};

class A<X> {} // special logic is generated
class A<Y> {} // special logic is NOT generated

Ответы [ 5 ]

3 голосов
/ 27 июня 2011

Вы можете использовать специализацию шаблонов или boost :: is_base_of из библиотеки повышающих черт Или, конечно, написать свои собственные черты, но не должны, поскольку вы еще не освоили шаблоны.

Используя специализацию, вы могли бы

template<T>
class A 
{
  void somefunction() {
     // generic version
  }
};
template<>
class A <Foo>
{
  void somefunction() {
     // foo version
  }
};

Как всегда, позвольте мне порекомендовать Vandevoorde / Josuttis "Шаблоны C ++: Полное руководство".

Если вы боитесь вздутия кода, потому что только одна функция-член измногие должны быть специализированными, вы все равно можете передать эту функцию на аутсорсинг:

template <typename T> struct somefunction_helper {
    static void thatfunction () {
        // generic form
    }
};
template <> struct somefunction_helper<Foo> {
    static void thatfunction () {
        // Foo form
    }
};

template<T>
class A 
{
  void somefunction()  {
     somefunction_helper<T>::thatfunction();
  }
};
2 голосов
/ 27 июня 2011

Для этого предназначены шаблонные специализации.Их сложнее написать, но это то, что вы делаете с ними.Например:

template<T> class A
{
    void somefunction(void) {
        ...//default for any object type.
    }
};

template<> class A<Foo>
{
    void somefunction(void) {
        ...//specific to the type Foo.
    }
};

Да, это требует дополнительной работы.Есть несколько способов метапрограммирования шаблонов, чтобы сделать это так, как вы хотите, но кто-то другой должен будет объяснить это.

1 голос
/ 27 июня 2011

Либо специализируйте A, либо делегируйте работу шаблона функции-члена someFunction() какому-нибудь бесплатному шаблону функции, который вы можете (полностью) специализировать на T.

0 голосов
/ 27 июня 2011

Поскольку специализация не будет работать, поскольку параметр шаблона будет получен только из Foo, используйте то, что сказал другой ответ: is_base_of, либо из Boost, либо из стандартной библиотеки, если она уже поддерживает части C ++0x:

#include <type_traits> // C++0x

class Foo{};

template<class T>
class A{
  void specialOnFoo(){
    // dispatch the call
    specialOnFoo(std::is_base_of<T, Foo>::type());
  }

  void specialOnFoo(std::true_type){
    // handle Foo case
  }

  void specialOnFoo(std::false_type){
    // non-Foo case
  }
};
0 голосов
/ 27 июня 2011

Редактировать # 2 - см. Рабочий пример. Обратите внимание, что это эквивалент времени специализации шаблона (который происходит во время компиляции) и требует RTTI.

#include <iostream>
#include <typeinfo>
using namespace std;

class Foo {};
class X: public Foo {};
class Y {};

template<typename T> class A {
public:
  void somefunction()
  {
    if (typeid(T) == typeid(X)) {
      cout << "X specific logic happening" << endl;
    }
    else {
      cout << "Default behavior" << endl;
    }
  }
};

int main() {
  A<X> ax;
  A<Y> ay;
  ax.somefunction(); // prints "X specific logic happening"
  ay.somefunction(); // prints "Default behavior"
}

typeid может использоваться с шаблонами для извлечения типа параметра шаблона - как описано ниже:

// expre_typeid_Operator_3.cpp
// compile with: /c
#include <typeinfo>
template < typename T > 
T max( T arg1, T arg2 ) {
   cout << typeid( T ).name() << "s compared." << endl;
   return ( arg1 > arg2 ? arg1 : arg2 );
}

Взято из: http://msdn.microsoft.com/en-us/library/fyf39xec(v=vs.80).aspx

Обратите внимание, что значение name() определяется реализацией.

...