简体   繁体   中英

variadic template matching and the SFINAE?

template<typename Signature>
class myfunction   //basic class template
{
};

template<typename R, typename... Args>
class myfunction<R (Args...)>   //normal function  specialized edition 
{
    typedef R (*Ptr)(Args...);
    Ptr m_p;
public:
myfunction(Ptr p) : m_p(p)
{

}
R operator()(Args... args)
{
    return m_p(args...);
}
};

template<typename R, typename T, typename ... Args>
class myfunction<R (T*, Args...)>  //member function specialized edition one
{
    typedef R (T::* mPtr)(Args...);
    mPtr m_p;
public:
    myfunction(mPtr p):  m_p(p)
    {

    }
    R operator()(T* likeThis, Args...args)
    {
        return   (likeThis->*m_p)(args...);
    }
};


template<typename R, typename T, typename ... Args>
class myfunction<R (T, Args...)>   //member function specialized edition two
{
    typedef R (T::* mPtr)(Args...);
    mPtr m_p;
public:
    myfunction(mPtr p):  m_p(p)
    {

    }
    R operator()(T likeThis, Args...args)
    {
        return   (likeThis.*m_p)(args...);
    }
};

template<typename R, typename T, typename ... Args>
class myfunction<R(T&, Args...)>   //member function specialized edition three
{
    typedef R (T::* mPtr)(Args...);
    mPtr m_p;
public:
    myfunction(mPtr p):  m_p(p)
    {

    }
    R operator()(T& likeThis, Args...args)
    {
    return   (likeThis.*m_p)(args...);
    }
};

int func1()
{
    cout << "func1";
    return 0;
    }

void func2(int x)
{
    cout << "func2";
    cout << x ;
}
int main()
{
    myfunction<int(void)> f1(func1);
    f1();
    myfunction<void(int)> f2(func2);//this will fail, why?
    f2(1);   
    return 0;
}

I want to mitate the function wrapper in standard library. The test code is like above. However, f1 can mathch the right one, this is normal function specialized edition. While f2 first match the member function specialized edition two, but after the failure of matching, it should go to match the normal function specialized edition and then succeed? This is just what SFINAE mean, am i right? After i comment out the member function specialized edition two, it match the one will, that why? please help me.

As pointed out in comments - this specialization is taking over your one arg free functions:

template<typename R, typename T, typename ... Args>
class myfunction<R (T, Args...)>   //member function specialized edition two
{
    typedef R (T::* mPtr)(Args...);
    mPtr m_p;
public:
    myfunction(mPtr p):  m_p(p)
    {

    }
    R operator()(T likeThis, Args...args)
    {
        return   (likeThis.*m_p)(args...);
    }
};

Easy answer is just remove this specialization and your program start compiling.

But - std::function implementation is not so easy as you might expect. You need to use type erasure technique to imitate its behavior - I mean myFunction<R(Arg...> on myFunction level shall serve for all - free functions and member functions - only during construction of specific object instance - you shall select "implementation" via the argument type - if it is member function or free function.

First you must define any function call abstraction:

template<typename R, typename T, typename ... Args>
class AnyFunctionCall
{
public:
    virtual ~AnyFunctionCall() {}

    virtual R call(T arg, Arg&&... args) const = 0;
};

I see you already know how to implement this interface for free function and member function.

template<typename R, typename T, typename ... Args>
class myfunction<R (T, Args...)>  
{
    std::unique_ptr<AnyFunctionCall> implementation;

public:
    template <typename Functor>
    myfunction(Functor p):  m_p(makeFunctionCall(std::forward<Functor>(p)))
    {

    }
    R operator()(T arg, Arg&&... args)
    {
        return implementation->call(arg, args...);
    }
};

You see - it is required to have one argument (object or first argument of free function). For zero argument function you might have your simple specialization for free function myfunction<R ()> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM