2010-11-08 2 views
2

Существует раздел кода в библиотеке я использую, который выглядит следующим образом:Wildcards в TypeID

... 
    if (ptype == typeid(Vector< T, 4 >)) 
     { 
     This->SetNumberOfComponents(4); 
     } 
    else if (ptype == typeid(Vector< T, 5 >)) 
     { 
     This->SetNumberOfComponents(5); 
     } 
... 

Если какой-либо способ сделать это более общий характер, делая что-то вроде

if (ptype == typeid(Vector< T, ANYTHING >)) 
     { 
     This->SetNumberOfComponents(THE_SECOND_TEMPLATE_PARAM); 
     } 

?

Спасибо,

Дэвид

+1

Можете ли вы создать шаблон с точным векторным типом, а не хранить объект типа? Это более условно и дает это тривиальное решение. – 2010-11-08 18:12:49

+0

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

+0

Roger, я хочу принять ваш ответ «просто не использовать typeid» - можете ли вы создать «ответ», а не «комментарий», чтобы я мог его принять? –

ответ

0

Мы приняли предложение Роджера Pâte по удалению использования TypeID пути реструктуризации немного (Это был первый комментарий, так что я не мог пометить его как ответ). Спасибо за все замечательные идеи и обсуждения!

3

У вас есть доступ к векторным классом?

Если да, то вы можете добавить статическое поле внутри векторного класса, который просто повторяет обратно второй параметр шаблона:

template<class T, int SIZE> 
class Vector 
{ 
    // ... 
    public: 
     static const int NUM_COMPONENTS = SIZE; 
    // ... 
}; 
+0

У меня есть доступ к классу векторов, но у меня нет экземпляра класса в этой функции, у меня есть только переменная ptype. –

2

оптимизирующий компилятор будет INLINE рекурсивного определения в эквивалент ваших, если лестницы:

template<typename T, size_t N> 
struct TestType { 
    static void Test (const std::type_info& ptype) { 
     if (ptype == typeid (Vector< T, N >)) 
      This->SetNumberOfComponents (N); 
     else 
      TestType < T, N - 1 >::Test (ptype); 
    } 
}; 

// need to have a base case which doesn't recurse 
template<typename T> 
struct TestType<T, 0> { 
    static void Test (const std::type_info& ptype) {} 
}; 

const size_t MAX_DIMENSIONS (12); 

template<typename T> 
void SetNumberOfComponents (VectorBase<T>* p) 
{ 
    const std::type_info& ptype (typeid (*p)); 

    TestType<T, MAX_DIMENSIONS>::Test (ptype); 
} 
+0

Это намного лучше, чем в настоящее время (без дублирования кода), но моя мотивация заключалась в том, чтобы разрешить произвольно длинные векторы (вы выбрали 12, библиотека выбрала 7, но что, если вы хотите вектор длины 128? Или 1000? Вам не нужно было бы проверять все эти типы 1000! –

+0

Если у вас 1000 разных типов, и единственная информация, которую вы должны различать между собой, - это идентификатор ptype, тогда вам придется проверять их все Было бы лучше, если бы Vector выставил свой размер вместо этого, но если вы ограничены только изменением кода клиента, вы получите уродливое и не масштабируете это хорошо (возможно, O (lnN), если сортировать имена типов , или менее с хэшмапом, но это все еще некрасиво). –

0

Возможно, вы можете совершить какой-то макрос взлома, поэтому вам не придется писать слишком много повторяющегося кода.

#include <boost/preprocessor/repetition/repeat.hpp> 
#include <typeinfo> 
#include <iostream> 

struct X 
{ 
    void SetNumberOfComponents(int n) { std::cout << n << '\n'; } 
}; 

template <class T, int N> 
struct Vector{}; 

typedef int T; 

void foobar(const std::type_info& ptype) 
{ 
    #define SUPPORTED_VECTOR_TYPES 20 
    #define BRANCH(z, n, text) else if (ptype == typeid(Vector<T, n>)) {This->SetNumberOfComponents(n);} 
    X x; 
    X* This = &x; 
    if (0); BOOST_PP_REPEAT(SUPPORTED_VECTOR_TYPES, BRANCH, UNUSED) 
    #undef SUPPORTED_VECTOR_TYPES 
    #undef BRANCH 
} 

int main() 
{ 
    foobar(typeid(Vector<int, 10>)); 
} 
+0

UncleBens, моя мотивация (должно была упомянуть об этом изначально, извините) на самом деле не ограничивала длину вектора. То есть, если пользователь хочет использовать длину 1000 вектор, это кажется безумным, чтобы сравнить его с каждым типом , ... пока он не совпадёт. Есть ли способ сделать это, не пройдя все типы? –

+0

Я думаю, это то, что вы получаете, когда пытаетесь использовать информацию типа ** во время выполнения **, а не компилировать время. - Как очень не портативное решение, вы можете проверить, что содержит строка имени. – UncleBens