Partial Specialization of Operator()

妖精的绣舞 提交于 2019-12-03 16:49:47

Usually, it goes like this:

template <typename A, typename B>
struct DoSomethingHelper
{
    static A doIt(const std::vector<B> &data);
};

template <typename B>
struct DoSomethingHelper<double, B>
{
    static double doIt(const std::vector<B> &data) { ... }
};

template <typename B>
struct DoSomethingHelper<int, B>
{
    static int doIt(const std::vector<B> &data) { ... }
};

template<class A, class B>
A do_something(const std::vector<B> &data)
{ return DoSomethingHelper<A, B>::doIt(data); }

Now that you've seen the classic forward to static method, there is actually another way when the type for which to specialize is "complete".

You may not be able to partially specialize a function, but you can perfectly overload it.

template <typename A, typename B>
A do(std::vector<B> const& data) { return this->doImpl(data, (A*)0); }

template <typename A, typename B>
A doImpl(std::vector<B> const& B, A*) { // generic implementation }

template <typename B>
int doImpl(std::vector<B> const& B, int*) { // int implementation }

template <typename B>
double doImpl(std::vector<B> const& B, double*) { // double implementation }

The trick is to pass an "unused" argument to doImpl for the sole purpose of actually selecting the right implementation (thanks to overload resolution).

Here I simply chose to pass (A*)0, because this does not involve A's constructor (in case it's non trivial).

This dispatch idiom is what is used in the STL to implement some algorithm with better efficiency for some iterator categories (for example, std::distance is O(1) for random iterators).

I find it much more lightweight that using a helper class with static methods and partial specializations... but maybe that's just me :)

People typically just forward to a static implementation.

template<class A, class B> class X;
template<class A, class B> friend class X;
template<class A, class B> class X {
public:
    static A do_something(class_type* not_this, const std::vector<B>& data) {
        //...
    }
};
// partially specialize
template<class A, class B>
A do_something(const std::vector<B> &data) {
    return X<A, B>::do_something(this, data);
};

Not a solution to your problem (there are a couple already there), but some of the things that are wrong in your code:

You are missing a struct or class keyword in the template class declaration:

template <typename A, typename B> struct do_something_implementation {
//                                ^^^^^^

Inside the class definition, member functions must not use a qualified name, regardless of whether the class is a template or not:

class A {
   void A::foo() {} // Error, should be: void foo() {}
};

Member template specializations cannot appear inside the class definition, but at the namespace level:

class B {
   template <typename T> void foo( T );
};
template <> void B::foo<int>( int ) {}
template <> void B::foo<double>( double ) {}

Plus on your case, the member function is not a template, but rather a non-templated member function (the template is the containing class, not the function itself). What your code is effectively trying to do is defining other class' member functions inside the general template, kind of trying to do.

Overall there was enough errors to make parsing the code almost impossible for the compiler to identify what you were trying to do and provide a good error message, but still, it should have provided any error message pointing to the first line that you copied instead of chocking to death.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!