avoid specifying redundant template parameters which contain templated function pointer

Deadly 提交于 2019-12-05 19:19:10

In this example u is not a function pointer, it's a type (the signature of a function pointer). If you want to store a function pointer you need to pass it.

template<class T, class F = void(*)(T&)>
void Foo(F f)
{
  // store the function pointer f here
}

called like so:

struct SomeType {};
void bar(SomeType& x);

Foo(&bar);

Is this what you mean to do?

Short answer: I don't think it is possible.

Long one.. When calling a template function, you cannot omit the first parameter and specify the second: the compiler would try to match your MyIntFunction to the template parameter T. Generally, you can specify the first, but omit the second if the compiler can infer the second template parameter. In this case, this is not an option however, because you want to specify the second parameter explicitly.

The second template parameter has a dependency (T) on the first template parameter. Therefore, reversing the order of the template parameters is also not an option.

Your best bet would be to define it in a way similar to what Richard suggested:

template<class T>
void Foo(T f)
{
   int a(1);
   f(a); // this forces f to be a function taking an int as parameter
}

Here is a dirty implementation which basically does what the OP was asking for. It depends on too many assumptions, but could be at least something to discuss. The idea is to specify in advance all possible types which can serve as function argument, and then deduce this type.

#include<iostream>

template<typename T>
struct TD; //type display

template<typename FunctionType, typename T, typename ... Ts>
struct ArgumentDeduction
{
    typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
                                     , T
                                     , typename ArgumentDeduction<FunctionType, Ts ...>::type
                                     >::type type;
};

template<typename FunctionType, typename T>
struct ArgumentDeduction<FunctionType, T>
{
    typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
                                     , T
                                     , void
                                     >::type type;    
};


template<typename FunctionType
       , typename T = typename ArgumentDeduction<FunctionType, int, double>::type >
void foo()
{
    TD<T>();
}

struct AvoidConversion
{
    struct DummyType{};
    template<typename T> DummyType operator()(T x) { return DummyType(); }    
};

struct Bar : public AvoidConversion
{
    using AvoidConversion::operator();

    void operator()(int x);
    //void operator()(double x);   //try also this
};

int main()
{
    foo<Bar>();  //calls the foo<Bar,int> version    
}

One main assumption here is the form of the Bar functor, which in principle accepts any type, but has a relevant implementation of type void only for the single allowed type.

Again, I don't think this is rather useful, but I guess this comes closest to the OP's question up to now.

DEMO


EDIT: Otherwise, i.e. without AvoidConversion in the code above, the compiler will perform an implicit conversion and the argument deduction gives true for all types which are convertible into each other (such that, e.g., int is deduced when there is only a function taking double).

If someone sees a way to avoid this ugly AvoidConversion hack and deduce the parameter type somehow more elegant, I would be interested in seeing that.

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