2012-06-12 57 views
3

这是一个简单的问题,我确信它已被回答,但我似乎无法找到一个好答案。模板的简单示例

我有一个类,点:

template<class T> 
Point{ 
\\code 
} 

...现在我想点,其中有一些T作为一个整数,具有T作为一个双矢量。我想写点东西像

template<class T> 
std::vector<Point<T> > points; 

但是,唉,这不符合“预期的‘模板’前主表达式”错误编译。我一直无法摆脱这个代码,使其工作。同样重要的是,点在主类中,所以我不能将模板声明粘贴到函数之外。

如果有人能指导我解决问题,我会非常感激。

谢谢。

+2

一个向量只能存放一种类型的元素。所以你可以选择点或点但你不能混合它们。 –

+0

不应该只是'std :: vector > points'? – knittl

+0

你想要一个模板化的'typedef'吗? – ereOn

回答

5

如果您的目标是拥有一个vector兼有Point<int>Point<double>您可以使用Boost Variant

typedef boost::variant<Point<int>, Point<double> > VariantPoint; 

然后:

std::vector<VariantPoint> my_vector; 

my_vector.push_back(Point<int>(1, 0)); 
my_vector.push_back(Point<double>(1.5f, 2.0f)); 

会工作。请注意,为了后续检查元素,您可能必须使用visitor pattern,如here所述。

如果你的目标是有一个只能容纳一种类型的Point区别向量类型,那么你可以使用:

template<typename T> using PointVector = std::vector<Point<T>>; // C++11 

// Now you can write: 
PointVector<int> my_vector; 

// Which is equivalent to: 
std::vector<Point<int>> my_vector; 

或者,如果C++ 11是不是一种选择:

template<typename T> struct PointVector 
{ 
    typedef std::vector<Point<T> > Type; 
} 

然后:

PointVector<int>::Type my_vector; 
+0

谢谢你的完整答案。根据我的理解,Boost和C++ 11不在标准C++库中,而且我正在编写将在不一定具有这些软件包的计算机上运行的代码。不过,我正在寻找您的第一个涉及变体的解决方案。有没有办法做到这一点没有提升? (说,如其他答案建议。) – alexvas

+0

@alexvas:如果您对挖掘Boost Variant代码感到满意,您可以轻松地重现它。或者你也许可以从Boost中提取文件(Boost有一个工具来提取它的干净的子集)。 Boost可以在很多平台上运行,也许你可以用自己的代码发布它(或者说服那些决定这么做的人?) – ereOn

2

为了得到一个单一的一种载体,我会用继承:

template <typename T> 
struct PointVector : public std::vector< Point<T> > 
{ 
}; 

请注意,继承只是实现模板typedef的等效机制。这意味着,PointVector不应该包含任何数据成员或虚拟功能。但是,@ ereOn的建议是首选,并在this question的答案中讨论。

实现变体的老式方法是使用联合。

class IntOrDouble { 
    union { 
     int i; 
     double d; 
    }; 
    bool is_int; 
    bool is_double; 
public: 
    IntOrDouble() : is_int(false), is_double(false) {} 
    IntOrDouble (int x) : is_int(true), is_double(false) { i = x; } 
    IntOrDouble (double x) : is_int(false), is_double(true) { d = x; } 
    int operator = (int x) { 
     is_int = true; 
     is_double = false; 
     return i = x; 
    }; 
    double operator = (double x) { 
     is_int = false; 
     is_double = true; 
     return d = x; 
    }; 
    operator int() const { 
     if (is_int) return i; 
     if (is_double) return d; 
     return 0; 
    } 
    operator double() const { 
     if (is_double) return d; 
     if (is_int) return i; 
     return 0; 
    } 
}; 
typedef std::vector< Point<IntOrDouble> > PointVector; 

但这一切似乎都在这个用例的顶部。我只是使用双向所有的载体,除非内存是真的紧。

+0

我不会倒下,但在这种情况下继承是错误的,原因有几个。最重要的原因是'std :: vector'不是被设计为公开继承的。我不确定标准说的是什么,但我非常怀疑它有一个虚拟的析构函数,这可能会导致一些微妙的问题。如果有的话,它应该是私人继承,但我不会推荐它。 – ereOn

+0

@ereOn:感谢您的输入。我已经很久以前使用过STL容器的继承了,所以我发现了解它可能是不安全的。我会对你找到的任何文档感兴趣,并支持它。问候。 – jxh

+0

@ereOn:我澄清了我的回答,指出继承仅用于执行模板typedef的手段。 – jxh