为 std::vector 编写 typedef 和 ostream 运算符

4

我创建了一个名为Chromosome的类,最终只是用vector来包装一个ostream运算符,所以我决定使用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个回答

7

很遗憾,由于编译器无法从函数声明中推断出 G 的类型,因此没有清洁的方法来做到这一点。

template<typename G>
std::ostream& operator<<(std::ostream& os, const typename Chromosome<G>::type& 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);

很遗憾,实际上没有更好的方法来解决这个问题。虽然在语言层面上禁止这样做是有充分理由的,但它确实阻止了你在这种情况下实现你想要的功能。


2
谢谢,我现在明白了这是如何工作的。使用向量完全没问题,因为我只是为了可读性而尝试使用Chromosome<G>::type。不过您能解释一下“这里不需要typename”的意思吗? - Rhys van der Waerden

1

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

const typename Chromosome<G>::type&

如需完整解释,请阅读Stack Overflow C++ FAQ文章“template”和“typename”应该放在依赖名称的哪里

正如@templatetypedef在评论中所提到的,虽然这将使代码编译通过,但它不会“起作用”,无法让您将std::vector<G>插入到std::ostream中,因为type处于无法推导的上下文中。

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

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

实际上,这样做行不通,因为编译器无法在此上下文中推断 G。这部分是因为您可以通过模板特化产生一些情况,使编译器无法知道要使用哪种类型。 - templatetypedef
@templatetypedef:很好,依赖名称不是唯一的问题。 - James McNellis
谢谢你的回答,我觉得templatetypedef的解释稍微清晰一些,所以我会采纳他的回答。 - Rhys van der Waerden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接