简体   繁体   English

用于std :: vector的Typedef和ostream运算符

[英]Typedef and ostream operator for a std::vector

I created a class Chromosome that ended up simply being a wrapper for vector with an ostream operator, so I've decided to typedef vector instead. 我创建了一个Chromosome类,最终只是用ostream运算符对vector进行了包装,因此我决定改用typedef vector。 However, I'm having trouble with the templated ostream operator... Is this the best way to go about it? 但是,我在使用模板化的ostream运算符时遇到了麻烦...这是最好的方法吗? (I've seen a few approaches and have failed to get any to work) (我已经看到了一些方法,但没有任何效果)

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;
}

At the moment the error I'm getting is: 目前,我得到的错误是:

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

Cheers. 干杯。

Unfortunately, there's no clean way to do this because the compiler can't deduce the type of G from the function declaration 不幸的是,没有干净的方法可以做到这一点,因为编译器无法从函数声明中推断出G的类型。

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

The reason is that if you were to specialize Chromosome for different types, you could end up in a situation where the compiler couldn't unambiguously infer G . 原因是,如果要专门针对不同类型的Chromosome ,则可能会遇到编译器无法明确推断G For example: 例如:

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;
};

Now, what would happen if you did this? 现在,如果您这样做,会发生什么?

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

The compiler can't tell if G is double or int in this case, because both Chromosome<int> and Chromosome<double> have vector<double> as their nested type. 在这种情况下,编译器无法确定Gdouble还是int ,因为Chromosome<int>Chromosome<double>都将vector<double>作为其嵌套类型。

To fix this, you'll have to explicitly use the type vector<G> as the argument: 要解决此问题,您必须显式使用vector<G>类型作为参数:

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

Unfortunately, there really isn't a better way of doing this. 不幸的是,确实没有更好的方法可以做到这一点。 It's not really a defect in the language, since there's a good reason to prohibit it, but it does actually prevent you from doing what you want to in this context. 这并不是语言的缺陷,因为有充分的理由要禁止它,但这实际上阻止了您在这种情况下做自己想做的事情。

The member typedef type is a dependent name: its meaning is dependent upon the template parameter G . 成员typedef type是从属名称:其含义取决于模板参数G You need to use a typename to tell the compiler that type names a type: 你需要使用一个typename来告诉编译器type名称的类型:

const typename Chromosome<G>::type&

For the full explanation, consider reading the Stack Overflow C++ FAQ article, Where to put the “template” and “typename” on dependent names . 有关完整的解释,请考虑阅读Stack Overflow C ++常见问题解答文章“将“模板”和“类型名”放在从属名称上的位置)

As @templatetypedef alludes to in the comments, while this will enable the code to compile, it won't "work" to allow you to insert an std::vector<G> into an std::ostream because type is in a nondeduced context. 正如@templatetypedef在注释中所暗示的那样,尽管这将使代码能够编译,但它不能“工作”以允许您将std::vector<G>插入到std::ostream因为type是非推断的上下文。

The easiest way to declare the overload and get the expected behavior is to use std::vector<G> directly as the argument type: 声明重载并获得预期行为的最简单方法是直接使用std::vector<G>作为参数类型:

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

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

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