【问题标题】:How to forward declare a C++ template class?如何转发声明 C++ 模板类?
【发布时间】:2012-11-30 16:05:08
【问题描述】:

给定一个类似如下的模板类:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

如何在头文件中前向声明这个类?

【问题讨论】:

    标签: c++ templates forward-declaration


    【解决方案1】:

    你会这样做:

    template<typename Type, typename IDType=typename Type::IDType>
    class Mappings;
    
    template<typename Type, typename IDType>
    class Mappings
    {
    public:
        ...
        Type valueFor(const IDType& id) { // return value }
        ...
    };
    

    请注意,默认值是在前向声明中,而不是在实际定义中。

    【讨论】:

      【解决方案2】:

      您可以声明一个模板化类,其定义声明了默认参数,但任何时候您引用该类时都必须包含其所有参数,直到定义被引入。

      例如。让我们使用 std::vector 而不包含它(std::vector 的第二个参数定义为默认值):

      namespace std
      {
          template<typename, typename>
          class vector;
      }
      
      #include <iostream>
      
      template <typename S, typename T>
      void Foo (const std::vector<S,T> & vector)
      {
          std::cout << "do vector stuff, eg., display size = "
              << vector.size() << std::endl;
      }
      
      template <typename T>
      void Foo (const T & t)
      {
          std::cout << "do non-vector stuff..." << std::endl;
      }
      

      然后我们可以在不使用包括向量的情况下使用它,例如:

      int main ()
      {
          Foo(3);
      }
      

      ...或者我们可以使用它和std::vector,例如:

      #include <vector>
      
      // Now the compiler understands how to handle
      // std::vector with one argument
      // (making use of its default argument)
      
      int main ()
      {
          Foo(std::vector<int>(3));
      }
      

      我没有检查标准,但这适用于 clang/gcc 和 -std=c++98 直到 -std=c++17,所以如果它不是正式的标准,那么它看起来是非官方的。

      【讨论】:

      • 也许你忘记了空尖括号Foo&lt;&gt; foo;。
      【解决方案3】:

      您只能为模板的第一个声明声明模板的默认参数。如果你想让用户转发声明一个类模板,你应该提供一个转发头。如果您想使用默认值转发声明其他人的类模板,那么您就不走运了!

      【讨论】:

        【解决方案4】:

        我的答案是对其他答案的补充,因为我发现的解决方案实际上通过创建一个新类型当所有参数都已知(或作为默认值提供)来减少对模板类前向声明​​的需求,以便这个新的类型,比你可以转发声明的,不再是模板:

        template<typename Type=MyDefault, typename IDType=typename Type::IDType>
        class MappingsGeneric
        {
        ...
        };
        
        class Mappings : public MappingsGeneric<> {};
        

        然后您可以class Mappings;。我知道这个解决方案并不适用于任何地方,但它适用于我的用例,因为我只在单元测试上下文中将模板用于非虚拟方法的高性能依赖注入。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-09-14
          • 2011-04-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多