C++ Forward声明using指令

Mik*_*e M 17 c++ c++11

我有一个标题,通过使用暴露模板类和typedef,如:

namespace fancy {

  struct Bar {
     ...
  }

  template<typename T>
  class Foo {
     ...
  }

  using FooBar = Foo<Bar>;
}
Run Code Online (Sandbox Code Playgroud)

我想转发声明在另一个标题中FooBar使用它shared_ptr.我试过了

namespace fancy {
  using FooBar;
}
Run Code Online (Sandbox Code Playgroud)

喜欢一个类或结构,但没有运气.这是可能的,如果是的话,怎么样?

Die*_*ühl 16

如果using不定义别名,则无法声明别名.但是,您可以声明类模板而不定义它,并使用重复的using别名:

namespace fancy {
    template <typename> class Foo;
    class Bar;
    using FooBar = Foo<Bar>;
}
Run Code Online (Sandbox Code Playgroud)


αλε*_*λυτ 6

使用前向声明的另一种方法是用using类继承替换:

// using FooBar = Foo<Bar>;
class FooBar : public Foo<Bar> {};
Run Code Online (Sandbox Code Playgroud)

当然,现在和现在FooBar不是一回事Foo<Bar>。例如,您需要通过继承可能存在的构造函数using Foo<Bar>::Foo,但作为一个好处,您可以像往常一样使用简单的前向声明。只是:

namespace fancy {
    class FooBar;
}
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您的 using 声明太大(很多模板参数,它们又由 using 语句定义),您还可以添加一个虚拟前向结构,该结构将 using 类型作为依赖类型:

    namespace fancy {

        struct Bar {
            ...
        }

        template<typename T>
        class Foo {
            ...
        }

        using FooBar = Foo<Bar>;

        // Forward struct
        struct FooBarFwd {
            using type = FooBar;
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后在您要转发的地方声明:

    namespace fancy {
        class FooBarFwd;
    }
    // use your type as
    typename FooBarFwd::type baz(const typename FooBarFwd::type & myFooBar);
    // instead of
    // FooBar baz(const FooBar & myFooBar);
Run Code Online (Sandbox Code Playgroud)

这种方法的一些缺点是

  • 用于typename消除依赖类型的歧义。
  • 对于您的类型有额外的间接性,某些编译器在报告错误时可能会出现问题。
  • 更改为这种方法可能需要对代码进行大量更改(更改每次出现的FooBarwith typename FooBarFw::type

因此,我建议仅当您确定自己在做什么时才应用此技术。