我有一堆模板参数,我想从我的用户隐藏。我怎样才能做到这一点?

时间:2010-06-17 16:44:44

标签: c++ templates

我有一个超类,它根据它使用的一些内部类型定义。子类化如下执行:

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 个答案:

答案 0 :(得分:2)

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 :(得分:1)

您可以更改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。后者实际上如下所示,Tchar

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

operator<<打印到输出流真的接受这样的类型,C ++编码器仍然不需要关心分配器或字符特征。正确的文档可以让他们轻松地使用std::string并将其传递出去并打印出来。

答案 2 :(得分:1)

  

用户真的不应该对内部类有任何了解,而且应该只关心自己使用该函数。

问题是每个不同的模板选项组合都定义了一个不同的类。

您无法执行以下操作

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(); }

答案 3 :(得分:0)

将以下typedef添加到Sub类:

typedef Super<internalTypeClass1,internalTypeClass2> MySuper;

现在你可以写

void function (Sub::MySuper *in);

答案 4 :(得分:0)

typedef的问题在于编译器在错误消息中使用完整的类名。也许这样的事情会更好:

class MySuper : public Super<internal1, internal2> {
    // forward constructors
}