【问题标题】:Forward class declaration with template using typename使用类型名的模板转发类声明
【发布时间】:2014-01-10 15:36:27
【问题描述】:

我有以下情况:-

template<typename Derived, typename ValType>
class foo
{
public:
    template<typename R>
    bar<typename std::vector<R>::const_iterator> select()
    {
        std::vector<R> translation;

        return bar<typename std::vector<R>::const_iterator>(std::move(translation));
    }
};

template<typename T>
class bar
    : public foo<bar<T>, typename std::iterator_traits<T>::value_type>
{
public:
    bar(std::vector<typename std::iterator_traits<T>::value_type>&& vec)
    {

    }
};

这基本上是我正在使用 CRTP 和 foo 作为 mixin 的一个小概念证明。

问题是我认为我应该使用前向声明,但是我尝试了以下方法:-

class bar; // I didn't expect this to work

但是我确实希望这会起作用:-

template<typename R>
class bar;

在我真正调用 select() 之前编译得很好

std::vector<int> enumerable_vector;
enumerable_vector.push_back(1);
enumerable_vector.push_back(2);

bar<typename std::vector<int>::const_iterator> baz(std::move(enumerable_vector));
baz.select<std::string>();

这会导致以下错误:-

错误错误C2027:使用未定义类型 'foo::bar'

任何帮助将不胜感激,谢谢!

【问题讨论】:

  • 它适用于 GCC 和 Clang,因为前向声明您期望工作。
  • @Daniel Frey 你在 baz 上调用 select() 吗?
  • 是的,只需点击我评论中的链接。
  • 我将前向类声明放入 foo.我认为它只会在这种情况下适用于本地,但下面的答案解决了问题

标签: c++ c++11


【解决方案1】:

错误错误 C2027:使用未定义类型 'foo::bar'

错误消息似乎表明您在foo 中转发声明了嵌套类型bar。您需要转发声明正确的类型(将bar 的声明移动到foo 的定义之上的命名空间级别)

【讨论】:

    【解决方案2】:

    编辑:这个答案不正确。 barselect定义 时不需要完整,当select 被实例化 时它必须是完整的。无需将select 的定义移到bar 的类说明符之后。


    问题是您在 foo 的类说明符中对 select 的定义要求 bar 是完整的。如果您转发声明 bar 并且仅在类说明符中 declare select,您可以将 select 的定义移动到 bar 完成的位置。 It then compiles fine:

    #include <iterator>
    #include <utility>
    #include <vector>
    
    template<typename T> class bar;
    
    template<typename Derived, typename ValType>
    class foo
    {
    public:
        template<typename R>
        bar<typename std::vector<R>::const_iterator> select();
    };
    
    template<typename T>
    class bar
        : public foo<bar<T>, typename std::iterator_traits<T>::value_type>
    {
    public:
        bar(std::vector<typename std::iterator_traits<T>::value_type>&& vec)
        {
    
        }
    };
    
    template<typename Derived, typename ValType>
    template<typename R>
    bar<typename std::vector<R>::const_iterator> foo<Derived, ValType>::select()
    {
        std::vector<R> translation;
        return bar<typename std::vector<R>::const_iterator>(std::move(translation));
    }
    

    【讨论】:

    • 很好的答案,但另一个答案为我解决了这个问题,因为这是一个让我在他发布后立即意识到我的错误的好时机。
    • @chrisw69:学习阅读错误信息,然后阅读错误信息是非常有价值的:)
    猜你喜欢
    • 2016-01-06
    • 2012-11-30
    • 2013-03-03
    • 1970-01-01
    • 2011-04-22
    • 2011-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多