std :: vector的Typedef和ostream运算符

时间:2011-02-12 01:33:50

标签: c++ templates vector typedef ostream

我创建了一个类Chromosome,它最终只是一个带有ostream运算符的vector的包装器,所以我决定改为使用typedef vector。但是,我在使用模板化的ostream运算符时遇到了麻烦......这是最好的方法吗? (我已经看到了一些方法,但没有得到任何工作)

template<typename G>
class Chromosome {
 public:
  typedef typename std::vector<G> type;
  typedef typename std::pair<type *,type *> ptr_pair;
};

template<typename G> //line 19 below:
std::ostream& operator<<(std::ostream& os, const Chromosome<G>::type& chromosome) {
  for(auto iter = chromosome.begin(); iter != chromosome.end(); ++iter)
    std::cout << *iter;
  return os;
}

目前我得到的错误是:

chromosome.h:19: error: expected unqualified-id before ‘&’ token
chromosome.h:19: error: expected ‘)’ before ‘&’ token
chromosome.h:19: error: expected initializer before ‘&’ token

干杯。

2 个答案:

答案 0 :(得分:6)

不幸的是,没有干净的方法来执行此操作,因为编译器无法从函数声明中推断出G的类型

template<typename G>
std::ostream& operator<<(std::ostream& os, const typename Chromosome<G>::type& chromosome);

原因是,如果您要为不同类型专门化Chromosome,最终可能会导致编译器无法明确推断G。例如:

template <typename G> class Chromosome {
public:
    typedef std::vector<G> type; // No typename needed here, BTW
};

template <> class Chromosome<int> {
public:
    typedef std::vector<double> type;
};

现在,如果你这样做会发生什么?

vector<double> v;
cout << v << endl;

在这种情况下,编译器无法判断Gdouble还是int,因为Chromosome<int>Chromosome<double>都有vector<double>作为他们的嵌套类型。

要解决此问题,您必须明确使用类型vector<G>作为参数:

template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome);

不幸的是,确实没有更好的方法。这并不是语言中的缺陷,因为有充分的理由禁止它,但实际上它确实阻止你在这种情况下做你想做的事。

答案 1 :(得分:1)

成员typedef type是一个从属名称:其含义取决于模板参数G。您需要使用typename告诉编译器type命名一个类型:

const typename Chromosome<G>::type&

有关完整说明,请考虑阅读Stack Overflow C ++ FAQ文章Where to put the “template” and “typename” on dependent names

正如@templatetypedef在评论中提到的那样,虽然这将使代码能够编译,但是它不会“工作”以允许您将std::vector<G>插入std::ostream因为{{1}在非弱化的上下文中。

声明重载并获得预期行为的最简单方法是直接使用type作为参数类型:

std::vector<G>