在带有deffrent类型的向量中使用模板结构

时间:2017-01-27 11:58:57

标签: c++ templates

您好我的c ++源代码

template <typename T>
struct Key
{
    string Name;
    T Value;
};

struct Block
{
    string Name;
    vector <Key> Keys; // I got error here ... !!!!
};

int main()
{
    Block thisBlock;

    Key <bool> Key1;
    Key <string> Key2;

    // Set key 1
    Key1.Name = "Key1";
    Key1.Value = false;

    // Set key 2
    Key2.Name = "Key2";
    Key2.Value = "Hey";

    // Set block with all keys
    thisBlock.Name = "Block1";
    thisBlock.Keys.push_back(Key1);
    thisBlock.Keys.push_back(Key2);

    return 0;
}

请指导我这个错误!我知道我必须在<>中使用vector <Key>,但如果我这样做,我的块密钥仅限于该类型!有没有办法解决这个问题?

错误

argument list for class template "Key" is missing (in block struct (vector <key>>)

2 个答案:

答案 0 :(得分:2)

Key<bool>Key<string>是两种不同的类型,彼此无关,因此,您无法将它们存储在一个std::vector中,就像您无法创建std::vector一样存储intfloat

要解决此问题,您可以为密钥创建一个公共基类,如下所示:

class KeyBase {
public:
    virtual ~KeyBase() = default;               // virtual destructor to avoid memory leaks
    std::string GetName() const { return name; }// some common functions
    virtual std::string ToString() const = 0;   // and some function to be overriden
    std::string name;                           // and members

    KeyBase(std::string name_) : name(name_) {};
    KeyBase() = default;
};

template<class T>
class Key : public KeyBase {
public:
    std::string ToString() const override { ... } // implementation of virtual functions
    T value;
};

...
std::vector<std::unique_ptr<KeyBase>> vk;
vk.push_back(std::make_unique<Key<bool>>());
vk.push_back(std::make_unique<Key<string>>());
std::cout << vk[0]->GetName() << ' ' << vk[1]->GetName(); // Works
std::cout << vk[0]->value << ' ' << vk[1]->value; // Does not work as KeyBase has no value
std::cout << dynamic_cast<Key<bool>*>(vk[0].get())->value; // Works as vk[0] is now casted
这里使用的

std::unique_ptr是一个智能指针类型 - 它的语义就像指针一样,但它是delete时的存储对象delete管理更容易。同样重要的是,std::vector存储指向KeyBase而非KeyBase的指针。这样做是为了避免对象切片。

此外,请谨慎使用std::dynamic_cast:如果您尝试转换为不正确的类型,它将返回nullptr

UP :要在push_back操作期间设置值,一种方法是使用辅助函数并设置构造函数:

template<typename T>
class Key : public KeyBase {
    ...
    Key(T val) : value(val) {}
    Key(T val, std::string name) : KeyBase(name), value(val) {}
}

template<typename T>
std::unique_ptr<Key<T>> createKey(T value) {
    return std::make_unique<Key<T>>(value);
}
template<typename T>
std::unique_ptr<Key<T>> createKey(T value, std::string name) {
    return std::make_unique<Key<T>>(value, name);
}

...
vk.push_back(createKey<bool>(false));
vk.push_back(createKey<string>("abc"));

实际上,通过这种方法,您甚至可以省略类型名称,如下所示:

vk.push_back(createKey(1, "abc")); // creates Key<int> with value 1 and name "abc"

但要特别注意这种遗漏,例如,"abc"的类型为const char*,因此createKey("abc")会创建Key<const char*>

答案 1 :(得分:1)

如果movsum(1:7,[0,2],'EndPoints','fill') - (1:7) ans = 5 7 9 11 13 NaN NaN 要使用通用Block,则必须将其设为模板:

Key

解决更常见的问题,您希望在同一向量中存储不同类型的对象,需要std::anystd::variant

template <typename T>
struct Block
{
    string Name;
    vector <Key <T>> Keys;
};

对于pre-C ++ 17,Boost库有boost::variantboost::any,它们可以做同样的事情。