std::vector 的 Typedef 和 ostream 运算符

发布于 2024-10-17 13:57:32 字数 847 浏览 2 评论 0原文

我创建了一个 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

干杯。

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. However, I'm having trouble with the templated ostream operator... Is this the best way to go about it? (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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

烟火散人牵绊 2024-10-24 13:57:32

不幸的是,没有干净的方法来做到这一点,因为编译器无法从函数声明中推断出 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,因为 ChromosomeChromosomevector 作为其嵌套类型。

要解决此问题,您必须显式使用 vector 类型作为参数:

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

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

Unfortunately, there's no clean way to do this because the compiler can't deduce the type of G from the function declaration

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. 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.

To fix this, you'll have to explicitly use the type vector<G> as the argument:

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.

此刻的回忆 2024-10-24 13:57:32

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

const typename Chromosome<G>::type&

有关完整说明,请考虑阅读 Stack Overflow C++ 常见问题解答文章 将“template”和“typename”放在依赖名称上的位置

正如 @templatetypedef 在注释中提到的,虽然这将使代码能够编译,但它不会“工作”以允许您将 std::vector 插入 std::ostream 因为 type 处于非推导上下文中。

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

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

The member typedef type is a dependent name: its meaning is dependent upon the template parameter G. You need to use a typename to tell the compiler that type names a 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.

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.

The easiest way to declare the overload and get the expected behavior is to use std::vector<G> directly as the argument type:

template<typename G>
std::ostream& operator<<(std::ostream& os, const std::vector<G>& chromosome)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文