У меня есть куча параметров шаблона, которые я хочу скрыть от своих пользователей.Как я могу это сделать? - PullRequest
2 голосов
/ 17 июня 2010

У меня есть суперкласс, который определен в терминах нескольких внутренних типов, которые он использует.Подклассы выполняются так:

template <class InternalType1, class InternalType2>
class Super 
{
    ...
}

class Sub : Super <interalTypeClass1, interalTypeClass2>
{ 
    ...
}

Но когда я хочу написать функцию, которая берет указатель на суперкласс, это происходит:

template <class InternalType1, class InternalType2>
void function(Super<InternalType1, InternalType2>* in) { ... }

Пользователь действительно не должен знатьчто-нибудь о внутренних классах, и на самом деле следует просто позаботиться об использовании функции.Некоторые из этих списков шаблонов становятся очень очень большими, и, по моему мнению, ожидать, что пользователь будет проходить их каждый раз, будет расточительно.

Есть предложения?

РЕДАКТИРОВАТЬ: функция должна знать используемые внутренние типы, поэтому, если нет способа доступа к типам шаблонов во время компиляции, я думаю, что нет решения?

Потенциальное решение: Пусть каждый класс сделает следующее:

#define SubTemplateArgs <SubTypeName, SubInternalType1, SubInternalType2>

?

Ответы [ 5 ]

2 голосов
/ 17 июня 2010
template <class TInternal1, TInternal2>
class Super {
    private:
        /*...*/
    public:
        typedef TInternal1 internal_type_1;
        typedef TInternal2 internal_type_2;
        /*...*/
};

typedef Super<int, char>    IntCharSuper;
typedef Super<bool, char>   BoolCharSuper;

class Sub1 : IntCharSuper {/*...*/};
class Sub2 : IntCharSuper {/*...*/};
class Sub3 : BoolCharSuper {/*...*/};


/***
 * functionA (below) can only take a pointer to an object of a
 * class which inherits from IntCharSuper
 **/
void functionA(IntCharSuper* in){
    IntCharSuper::internal_type_1 internal1_variable;
    IntCharSuper::internal_type_2 internal2_variable;
    // we now have 2 variables of the internal types...
}

/***
 * functionB (below) can take a pointer to an object of a class which inherits from any kind of Super, 
 * no matter what the template parameters of that Super are.
 * so functionB will work for types which inherit from 
 *    IntCharSuper, BoolCharSuper, Super<YourCustomType, void*>, or anything else for TInternal1 and TInternal2.
 **/
template <class TSuper>
void functionB(TSuper* in) {
    typename TSuper::internal_type_1 internal1_variable; /* typename is needed here */
    typename TSuper::internal_type_2 internal2_variable; /* typename is needed here */
    // we now have 2 variables of the internal types...
}

int main(int argc, const char* argv) {
        Sub1 s1;
        Sub2 s2;
        Sub3 s3;
        functionA(&s1);  //OK, s1 inherits IntCharSuper
        functionA(&s2);  //OK, s2 inherits IntCharSuper
        functionA(&s3);  //ERROR, s3 hasnt got IntCharSuper as parent

        functionB(&s2); //OK, s2 inherits from a class which defines internal_type_1 and internal_type_2
        functionB(&s3); //OK, s3 inherits from a class which defines internal_type_1 and internal_type_2

        return 0;
}
1 голос
/ 17 июня 2010

Пользователь действительно не должен ничего знать о внутренних классах и должен просто задуматься об использовании функции.

Проблема в том, что каждая комбинация опций шаблона определяет свой класс.

Вы не можете сделать следующее

vector<Super<int,int>> a;
a.push_back( Super<float,float>() );

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

Вы можете назвать различные комбинации (как уже предлагалось), используя typedef, или, возможно, вы можете использовать более общий родительский класс, на котором основан Super.

class SuperDoooper {
  virtual SomeMethod();
}
template <class InternalType1, class InternalType2>
class Super 
{
    SomeMethod() { InternalType1.. }
}

class Sub : Super <interalTypeClass1, interalTypeClass2>
{ 
    ...
}


function( SupoerDoooper *in ) { in->SomeMethod(); }
1 голос
/ 17 июня 2010

Вы можете изменить Super интерфейс

template <class Types>
class Super {
    ...
};

class SubTypes {
  typedef interalTypeClass1 InternalType1;
  typedef interalTypeClass2 InternalType2;
};

class Sub : public Super <SubTypes> { 
    ...
};

Тогда ваш шаблон функции выглядит более удобным для пользователя

template <class Types2>
void function(Super<Types>* in) { 
    ... 
}

Sub s;
// ...
function(&s); 

Но пользователю не нужно заботиться об этих аргументах - компилятор сам вычисляет аргументы шаблона, если пользователь передает правильный аргумент функции, как в примере. Подумайте о std::operator<< и std::string. Последний действительно выглядит следующим образом, с T, являющимся char

std::basic_string< T, std::char_traits<T>, std::allocator<T> >

И operator<<, печатающий его в выходной поток, действительно принимает такой тип, тем не менее кодерам C ++ не нужно заботиться о распределителях или чертах символов. Существует надлежащая документация, которая научит их легко использовать std::string, просто разослать и распечатать.

0 голосов
/ 17 июня 2010

Проблема с typedefs заключается в том, что компиляторы используют полное имя класса в сообщениях об ошибках. Может быть, что-то подобное будет работать лучше:

class MySuper : public Super<internal1, internal2> {
    // forward constructors
}
0 голосов
/ 17 июня 2010

добавьте следующую typedef в подкласс:

typedef Super<internalTypeClass1,internalTypeClass2> MySuper;

Теперь вы можете написать

void function (Sub::MySuper *in);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...