0

我希望编写一个可以接受 2 或 3 个类型名的模板化结构。但是,程序会产生错误,template<class F1, class F2, class F3>...' cannot be overloaded. 如何纠正?

template< typename F1, typename F2, typename F3>    // this shouldn't be right because the compiler expects three typenames, and the program can provide two 
struct Force{
    F1 force1;
    F2 force2;
    F3 force3;

    Force(F1 f1, F2 f2) : force1(f1), force2(f2) {    // construct out of two forces
    }

    Force(F1 f1, F2 f2, F3 f3) : force1(f1), force2(f2), force3(f3) {   // construct out of three forces
    }

    Point operator()(double t) {
        return force1(t) + force2(t);
    }

    Point operator()(double t) {    // this overloading should not be right because it has the same signature as above
        return force1(t) + force2(t) + force3(t);
    }   
};

// this is used by the main program
      template< typename F1, typename F2>
      Force<F1, F2> make_physics(F1 first, F2 second){ 
        return Force<F1, F2>(first, second);
      }

// this is used by the main program
      template< typename F1, typename F2, typename F3>
      Force<F1, F2, F3> make_physics(F1 first, F2 second, F3 third){ 
        return Force<F1, F2, F3>(first, second, third);
      }  
4

3 回答 3

2

为了简化演示,我将类型替换Pointdouble. 下面的代码应该足以说明我的观点:

// This will be the default F3 argument. It's basically a "zero force".
struct zero {
    double operator()(double) { return 0.0; } 
};

// You only need one struct Force
template< typename F1, typename F2, typename F3 = zero>
struct Force {

   F1 force1;
   F2 force2;
   F3 force3;

   Force(F1 f1, F2 f2, F3 f3 = zero()) : force1(f1), force2(f2), force3(f3) {   // construct out of three forces
   }

   double operator()(double t) {
       return force1(t) + force2(t) + force3(t);
   }   
};

// You might provide two make_physics overload for 2D and 3D problems (that's what you want, right?)
template< typename F1, typename F2>
Force<F1, F2> make_physics(F1 first, F2 second){ 
    return Force<F1, F2>(first, second);
}

template< typename F1, typename F2, typename F3>
Force<F1, F2, F3> make_physics(F1 first, F2 second, F3 third){ 
    return Force<F1, F2, F3>(first, second, third);
}

如果您的编译器具有良好的 C++11 覆盖率,那么您可以用make_physics可变参数模板函数替换 的重载。此外,由于这是一个工厂函数,它只是将其参数转发给Force的构造函数,因此您应该使用通用引用和完美转发。代码应该是这样的:

template< typename F1, typename F2, typename... F3>
Force<F1, F2, F3...> make_physics(F1&& first, F2&& second, F3&&... third){ 
    return Force<F1, F2, F3...>(std::forward<F1>(first), std::forward<F2>(second), std::forward<F3>(third)...);
}
于 2013-03-24T18:58:35.727 回答
1

您可以阅读有关http://en.wikipedia.org/wiki/Variadic_template(可变参数模板)的信息。

或者您可以为模板提供如下默认参数:

template< typename F1, typename F2 = void, typename F3 = void>  

两者都还没有在 Visual Studio 2012 中实现但是......不确定你使用的是什么

或者(你可能不喜欢那样)复制你的类(不同的名字......)和模板每个上面的 1、2 和 3 个参数......

于 2013-03-24T18:22:59.220 回答
1

您可以将可变参数模板元组一起使用:

template<typename... F>
struct Force
{
    std::tuple<F...> f;
};

您还可以提供不同的专业化(此方法在 C++03 中使用):

template<typename F1, typename F2 = void, typename F3 = void>
struct Force
{
    F1 a;
    F2 b;
    F3 c;
};

template<typename F1, typename F2>
struct Force<F1,F2,void>
{
    F1 a;
    F2 b;
};

// and so on...
于 2013-03-24T18:48:34.237 回答