【问题标题】:Decoupling nested classes: "conflicting declaration of template" error when using template aliases解耦嵌套类:使用模板别名时出现“模板声明冲突”错误
【发布时间】:2017-08-30 23:45:32
【问题描述】:

按照this question 的建议,我使用后期模板实例化来解耦两个类,AB,它们都相互引用:

#include <iostream>
#include <memory>

template <typename T>
class Bbase {
};      

template <typename T> class BImpl;

template <typename T>
class AImpl
{
public:
    typedef boost::shared_ptr<AImpl> Ptr;
    typename BImpl<T>::Ptr foo();
};

template <typename T>
class BImpl
{
public:
    typedef boost::shared_ptr<BImpl> Ptr;
    typename AImpl<T>::Ptr bar();
};


typedef AImpl<void> A;
typedef BImpl<void> B;

int main () {
        A a;
        B b;
        return 0;
}

上面的编译没有错误。

但是,如果我尝试在其他地方实现 B 并定义一个别名类,则会出现以下编译错误:

#include <iostream>
#include <memory>

template <typename U>
class Bbase {
public:
    typedef std::shared_ptr<Bbase> Ptr;
    typename U::Ptr bar();
};      

template <typename T> class BImpl;

template <typename T>
class AImpl
{
public:
    typedef std::shared_ptr<AImpl> Ptr;
    typename BImpl<T>::Ptr foo();
};

template <typename T>
using BImpl = Bbase< AImpl<T> >;

typedef AImpl<void> A;
typedef BImpl<void> B;

int main () {
        A a;
        B b;
        return 0;
}

编译器:

$ g++ foo.cpp --std=c++14                                                                                                                                                                        
foo.cpp:22:32: error: conflicting declaration of template ‘template<class T> using BImpl = Bbase<AImpl<T> >’                                                                                                                                                  
 using BImpl = Bbase< AImpl<T> >;
                                ^
foo.cpp:11:29: note: previous declaration ‘template<class T> class BImpl’
 template <typename T> class BImpl;
                             ^
foo.cpp: In instantiation of ‘class AImpl<void>’:
foo.cpp:28:4:   required from here
foo.cpp:18:28: error: invalid use of incomplete type ‘class BImpl<void>’
     typename BImpl<T>::Ptr foo();
                            ^
foo.cpp:11:29: error: declaration of ‘class BImpl<void>’
 template <typename T> class BImpl;
                             ^
foo.cpp: In function ‘int main()’:
foo.cpp:29:4: error: aggregate ‘B b’ has incomplete type and cannot be defined
  B b;
    ^

我了解编译器错误,我正在尝试重新定义模板,但我不理解:

  • 为什么第一个代码 sn -p 有效?是在第一种情况下实现,在后一种情况下(重新)定义?
  • 我可以将B 前向声明为模板类,然后再将其声明为别名类吗?

我最想做的是:

using A = std::vector< B::iterator >;
using B = std::vector< A::iterator >;

【问题讨论】:

  • “我如何使用在其他地方实现的B 类(如模板)来实现这种情况?” 请详细说明。我不确定你的意思。
  • @cdhowie 感谢您的反馈,我详细说明了我想要实现的目标。如果需要更多说明,请告诉我。 :)
  • 我仍然不清楚你的实际目标是什么。一个实际的例子会有所帮助。伪代码在这里用处不大,因为我可以看到多种简化它的方法,这些方法可能不适用于真实代码。 (For example)

标签: c++ nested


【解决方案1】:

在第二个例子中,你有这个,它前向声明了一个模板类:

template <typename T> class BImpl;

然后你尝试这样做,它声明了一个模板别名:

template <typename T>
using BImpl = Bbase< AImpl<T> >;

但别名不是类——您不能使用别名来定义类。编译器会告诉你:

foo.cpp:22:32: error: conflicting declaration of template ‘template<class T> using BImpl = Bbase<AImpl<T> >’

为什么第一个代码 sn -p 有效?是在第一种情况下实现,在后一种情况下(重新)定义?

第一个代码 sn-p 有效,因为它格式正确;很简单,没有什么可以让它不起作用。在第二种情况下,您定义了一个与类同名的别名,这是不允许的。

我可以将B 前向声明为模板类,然后再将其声明为别名类吗?

没有。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    相关资源
    最近更新 更多