【问题标题】:Typedef and ostream operator for a std::vector用于 std::vector 的 Typedef 和 ostream 运算符
【发布时间】:2011-06-25 22:23:10
【问题描述】:

我创建了一个 Chromosome 类,它最终只是一个带有 ostream 运算符的向量包装器,因此我决定改为 typedef 向量。但是,我在使用模板化 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

干杯。

【问题讨论】:

    标签: c++ templates vector typedef ostream


    【解决方案1】:

    成员typedef type是一个依赖名:它的含义依赖于模板参数G。您需要使用typename 告诉编译器type 命名了一个类型:

    const typename Chromosome<G>::type&
    

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

    正如@templatetypedef 在 cmets 中所暗示的那样,虽然这将使代码能够编译,但它不会“工作”允许您将 std::vector&lt;G&gt; 插入到 std::ostream 中,因为 type 是在非推导中上下文。

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

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

    【讨论】:

    • 实际上,这是行不通的,因为编译器无法在这种情况下推导出 G。这部分是因为您可以通过模板专业化产生一些编译器不知道要使用哪种类型的情况。
    • @templatetypedef:好点;从属名称不是这里唯一的问题。
    • 感谢您的回答,我发现 templatetypedef 稍微清楚一点,所以他得到了这个。
    【解决方案2】:

    不幸的是,没有干净的方法可以做到这一点,因为编译器无法从函数声明中推断出 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&lt;int&gt;Chromosome&lt;double&gt; 都将vector&lt;double&gt; 作为它们的嵌套类型。

    要解决此问题,您必须明确使用类型 vector&lt;G&gt; 作为参数:

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

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

    【讨论】:

    • 谢谢,我现在明白这是怎么回事了。使用向量完全没问题,因为我只是想使用 Chromosome::type 来提高可读性。你能解释一下“这里不需要类型名”吗?
    猜你喜欢
    • 2018-03-31
    • 2017-04-13
    • 2018-12-16
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    • 2023-01-09
    • 2011-08-09
    • 1970-01-01
    相关资源
    最近更新 更多