简体   繁体   English

我们可以用C ++中的非模板类“包装”模板类吗?

[英]Can we “wrap” templated classes with non-templated classes in C++?

Disclaimer: I am afraid the short answer to my question is "not possible". 免责声明:恐怕我的问题的简短答案是“不可能”。 But since I am not a C++ expert, I thought I still give it a try and ask here, maybe there is some kind of solution which I am just not aware of. 但是由于我不是C ++专家,所以我认为我仍然可以在这里尝试一下,也许有某种我不知道的解决方案。

So I have templated container-like class MyContainer that internally stores data in a std::list<T> , where T is the class template type. 因此,我有模板化的类似于容器的类MyContainer ,它在内部将数据存储在std::list<T> ,其中T是类模板类型。 This works fine. 这很好。

Now I want to add another class, which has to map instances of that templated container class in a std::map<std::string, MyContainer> . 现在,我想添加另一个类,该类必须在std::map<std::string, MyContainer>该模板化容器类的实例。 However, the compiler asks me to provide the template class type for the value-part of the map, as in std::map<std::string, MyContainer<T>> . 但是,编译器要求我为映射的值部分提供模板类类型,如std::map<std::string, MyContainer<T>> But I would rather omit this template here, since that would in turn require me to use templates for the wrapper class as well. 但是我宁愿在这里省略该模板,因为这反过来又需要我为包装器类使用模板。

Thus my question: Is there a way to achieve what I am trying to do, omitting the template type for the wrapper class, at least to some extend? 因此,我的问题是:是否有一种方法可以实现我想要做的事情,至少要在某种程度上省略包装类的模板类型? Or is this just not possible in C++, because the compiler needs that information in any case? 还是在C ++中这是不可能的,因为在任何情况下编译器都需要该信息?

One common technique for doing this is inheritance. 做到这一点的一种常用技术是继承。

You make MyContainer<T> inherit from some base class, such as MyBaseContainer . 您使MyContainer<T>继承自某些基类,例如MyBaseContainer MyBaseContainer is not a template class, but MyContainer is. MyBaseContainer不是模板类,但MyContainer是模板类。 The MyBaseContainer class has virtual functions that the templated class overrides. MyBaseContainer类具有模板类覆盖的虚函数。

Then, you make your map of type std::map<std::string, MyBaseContainer*> . 然后,使您的地图类型为std::map<std::string, MyBaseContainer*> It will be able to call the virtual functions on the containers it stores, without having to know the template type of each one. 它将能够在其存储的容器上调用虚拟函数,而不必知道每个容器的模板类型。

This is how std::function works. 这就是std::function工作方式。

This is possible but a bit tricky. 这是可能的,但有点棘手。 If i understand you correctly you want each MyContainer class stored inside map to possibly have different template specialization (say some will hold std::list<int> while other will hold std::list<string> ) then you value type for map can no longer be just MyContainer but rather class that could hold both list<int> and list<string> . 如果我正确理解您的要求,那么您希望map存储的每个MyContainer类都可能具有不同的模板专业化(例如,某些将容纳std::list<int>而另一些将容纳std::list<string> ),那么您可以为地图的值类型不再仅仅是MyContainer ,而是可以容纳list<int>list<string>

One way to do it to use inheritance as @IanPudney already pointed out. 正如@IanPudney所指出的,使用继承的一种方法。

However you can do this even without creating inheritance hierarchy for MyContainer classes if you instead declare map as map<string, boost::any> (see http://www.boost.org/doc/libs/1_61_0/doc/html/boost/any.html ) that way you will be able to store any kind of MyContainer inside this map without the need to create inheritance hierarchy in advance. 然而,你可以做到这一点,即使没有创建继承层次MyContainer类,如果你不是声明地图作为map<string, boost::any> (见http://www.boost.org/doc/libs/1_61_0/doc/html/ boost / any.html ),这样您就可以在此映射中存储任何类型的MyContainer而无需事先创建继承层次结构。

There are two possible ways to do this without using inheritance but this may also depend on a few deciding factors. 有两种不使用继承的方式来执行此操作,但这也可能取决于一些决定性因素。 The first question is: Upon creating an instance of the outside class is the type of the template container known. 第一个问题是:创建外部类的实例时,已知模板容器的类型。 If it is then this is an easy class to write. 如果是,那么这是一个易于编写的类。 If it is not then it can still be done but there would be more work involved. 如果不是这样,那么仍然可以完成,但是会涉及更多的工作。 If case is not known there are 2 ways to do this and the first is the one you are trying to avoid by not making this a class template. 如果不区分大小写,则有两种方法可以做到这一点,第一种是您不通过将其设为类模板而试图避免的方法。 The second involves more work which some of the logic on how to define this class will be shown. 第二个涉及更多的工作,将显示有关如何定义此类的一些逻辑。

Pseudo Code: -- 1st Case Where Type Is Known Upon Creation 伪代码: -第一种情况,创建时知道类型

#include <map> 

template<class T>
class MyContainer {
    // ... Class Variables, Constructors & Methods
}

// For Demonstration We will say that `T` is known to be an int upon instantiation
class MyClass {
private:
    std::map< std::string, MyContainer<int> > maps_;

public:
    MyClass() {}
    ~MyClass() {
        // Clear Out Map
    }

    void addItem( std::string& str, int value ) {
        maps_.insert( std::make_pair( str, MyContainer<int>( value ) ); 
    }        
};

Now for the 2nd case where the type is not known using the method without templating the wrapper you will need to know of all of the types that this class can support and you will need to create typedef of each of these. 现在,对于第二种情况,在不使用包装模板的情况下使用该方法不知道类型的情况下,您将需要了解此类可以支持的所有类型,并且需要为每个类型创建typedef

Pseudo Code -- 2nd Case Where Type Is Not Known: 伪代码 -类型未知的第二种情况:

#include <map> 

template<class T>
class MyContainer {
    // ... Class Variables, Constructors & Methods
}

// For Demonstration We will say that `T` is unknown before instantiation
class MyClass {
public:
    typedef MyContainer<int> INTS;
    typedef MyContainer<float> FLOATS;
    typedef MyContainer<double> DOUBLES;
    // And Do This For Every Type This Class Will Support.

private:
    std::map< std::string, INTS >    mapInts_;
    std::map< std::string, FLOATS >  mapFloats_;
    std::map< std::string, DOUBLES > mapDoubles_;
    // And You Will Need A Container For Each Supporting Type
public:

    MyClass() {}
    // If You Have Constructors Other Than Default That Excepts Parameter Types
    // You Will Need A Constructor For Each Supporting Type

    ~MyClass() {
        // Clear Out All Maps
    }

    void addInts( std::string& str, MyClass::INTS );
    void addFloats( std::string& str, MyClass::FLOATS );
    void addDoubles( std::string& str, MyClass::DOUBLES );
    // And You Will Need A Corresponding Function For Each Type This Class Supports.

};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM