繁体   English   中英

模板结构向量

[英]vector of template struct

using namespace std;
#include <vector>
#include <string>

template <class T>
struct ValNode {
    string id;
    T value;
};

class ValTable {
public:
    ValTable();
    template <class T>
    void add(string,T);
    const bool find(string);
    void remove(string);
private:
    template<class T>
    std::vector<ValNode<T>*> vals;
};

编译器错误: error: data member 'vals' cannot be a member template

我确实尝试在结构中使用 T* 值,但我没有解决。 我还没有使用代码中的任何功能。 只是想把它编译成 *.o 文件(也有 .cpp 文件)。

正如错误所说,变量(包括数据成员)不能是模板; 只有类和函数可以。

看起来您希望表能够保存各种不同类型的值,根据传递给add()类型在运行时指定。 为此,您需要动态类型,C++ 不直接支持动态类型 为此,您可能会考虑使用Boost.AnyBoost.Variant 之类的库。

另一方面,也许您只想在每个表中存储一个类型,而在不同的表中存储不同的类型。 在这种情况下,类本身需要是一个模板:

template <typename T>
class ValTable {
public:
    ValTable();
    void add(string,T);
    const bool find(string);
    void remove(string);
private:
    std::vector<ValNode<T>*> vals;
};

在 C++ 中,您可以在类中有模板方法,但不能有模板数据成员。 例如:

template<typename T, int n>
struct FixedVector {
    T x[n];
    FixedVector() {
        for (int i=0; i<n; i++) x[i] = 0;
    }

    template<typename C>
    void copy(const C& container) {
        if (container.size() != n) {
            throw std::runtime_error("Wrong size");
        }
        int j = 0;
        for (typename C::const_iterator i=container.begin(),
                                        e=container.end();
             i!=e;
             ++i)
        {
            x[j++] = *i;
        }
    }
};

使用上面的类,您可以声明FixedVector<int, 5> f并调用f.copy(v)其中v可以是例如向量或列表或任何具有size beginend 所以FixedVector::copy是一个模板方法,这意味着编译器将为您将传递给函数的每个不同类型生成它的不同版本。

std::vector<double> y;
y.push_back(3.4); y.push_back(5.6); y.push_back(7.8);

std::list<unsigned char> z;
z.push_back('a'); z.push_back('b'); z.push_back('c');

FixedVector<int, 3> v;
v.copy(y);  // This is ok
v.copy(z);  // This is ok too

C++ 不允许模板数据成员,因为这意味着不同的类大小取决于您在特定编译单元中使用的类型数量,并且这与一次一个单元的 C++ 编译模型不符.

添加方法很好,因为它不会影响类的大小,并且可以在链接时通过避免从不同的编译单元中提取同一方法的多个副本来修复所有内容。

您必须将ValTable声明为模板

template <class T>
class ValTable{
public:
    ValTable();
    //template <class T>
    void add(string,T);
    const bool find(string);
    void remove(string);
private:
    //template<class T>
    std::vector<ValNode<T>*> vals;
};

您将无法做到ValTable需要成为模板

你可以有这个:

template <class T> //Make the class as template
class ValTable {
public:
    ValTable();
    template <class X>
    void add(string,X);
    const bool find(string);
    void remove(string);
private:
    //template<class T>
    std::vector<ValNode<T>*> vals;
};

您不能拥有模板成员值:每个翻译单元可以访问不同的实例,从而导致不同的对象布局。 您需要以某种方式分解出类型。

标准库按照你想要的std::locale做一些事情:每个std::locale存储不同类型对象的集合。 它是社会目的,不能直接用于您的目的。

基本思想是自动将使用的每个类型映射到一个int ,然后用int将类型映射到一个实例。 vals成员将成为查找正确实例的函数模板。 粗略的轮廓可能如下所示:

int type_index_alloc() { 
    static std::atomic<int> current(0);
    return ++current;
}
template <typename T>
int type_map() {
    static int rc = type_index_alloc();
}
class container {
    struct base { virtual ~base() {} };
    template <typename T>
    struct value: base { T v; };
    std::map<int, std::shared_ptr<base>> vals_;
public:
    T& vals()  {
        std::shared_ptr<base>& rc(vals_[type_map<T>()]);
        if (!rc) {
            rc = std::make_shared<value<T>>()); }
        return static_cast<value<T>&>(*rc).v;
    }
};

这只是试图展示事情是如何设置的:我目前无法访问编译器。 此外,代码示例仅提供对T类型对象的访问,但可以轻松更改为使用std::vector<T>代替。

暂无
暂无

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

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