我应该如何重载模板化结构?

时间:2013-03-24 18:10:11

标签: c++ templates struct overloading

我希望编写一个模板化结构,以便接受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);
      }  

3 个答案:

答案 0 :(得分:2)

为简化演示,我已将Point替换为double。下面的代码应足以说明我的观点:

// 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的构造函数,因此您应该使用universal references并完善转发。代码应该是:

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)...);
}

答案 1 :(得分:1)

您可以阅读http://en.wikipedia.org/wiki/Variadic_template(可变参数模板)..

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

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

两者尚未在visual studio 2012中实现,但是...不确定您使用的是什么

或(你可能不喜欢) 复制你的班级(不同的名字..) 并模板上面的1,2和3个参数......

答案 2 :(得分:1)

您可以使用variadic templatestuple

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...