我创建了一个 Chromosome 类,它最终只是带有 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

干杯。

有帮助吗?

解决方案

不幸的是,没有干净的方法来做到这一点,因为编译器无法推断出类型 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);

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

其他提示

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

const typename Chromosome<G>::type&

有关完整说明,请考虑阅读 Stack Overflow C++ 常见问题解答文章, 将“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)
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top