Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# to C++11 conversion: delegate templates

I'm trying to convert this C# code to C++:

public delegate void Action<in T>(T obj);
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
public delegate void Action<in T1, in T2, in T3>(T1 arg1, T2 arg2, T3 arg3);

Pretty clear this calls for std::function. Since this is a larger project I used a tool to do all the conversion and this is what it came up with:

#include <functional>

    template<typename T>
//C# TO C++ CONVERTER TODO TASK: C++ does not allow specifying covariance or contravariance in a generic type list:
//ORIGINAL LINE: public delegate void System::Action<in T>(T obj);
    using std::function<void()> = std::function<void (T obj)>;

    template<typename T1, typename T2>
//C# TO C++ CONVERTER TODO TASK: C++ does not allow specifying covariance or contravariance in a generic type list:
//ORIGINAL LINE: public delegate void System::Action<in T1, in T2>(T1 arg1, T2 arg2);
    using std::function<void()> = std::function<void (T1 arg1, T2 arg2)>;

    template<typename T1, typename T2, typename T3>
//C# TO C++ CONVERTER TODO TASK: C++ does not allow specifying covariance or contravariance in a generic type list:
//ORIGINAL LINE: public delegate void System::Action<in T1, in T2, in T3>(T1 arg1, T2 arg2, T3 arg3);
    using std::function<void()> = std::function<void (T1 arg1, T2 arg2, T3 arg3)>;

I assumed using std::function<void()> is a translation error, so I changed them to Action. So, my final version is this:

template<typename T>
using Action = std::function<void(T obj)>;

template<typename T1, typename T2>
using Action = std::function<void(T1 arg1, T2 arg2)>;

template<typename T1, typename T2, typename T3>
using Action = std::function<void(T1 arg1, T2 arg2, T3 arg3)>;

But this doesn't compile, with the understandable error that Action is already defined (when reaching the second using line). However, there's the possibility to have template functions with overloads (same name, different template parameters), so I wonder why this doesn't work for my alias templates. Is it simply not supported or do I miss something?

Also, maybe I did not fully understand co- and contravariance, but in my opinion they do not apply to this problem (no type inheritance involved here), so I don't see what the converter tool wants to tell me by these comments.

like image 413
Mike Lischke Avatar asked Nov 10 '22 09:11

Mike Lischke


1 Answers

JoachimPilebord doesn't want to answer, so I do it for completeness. The solution is to use a template parameter pack like this:

template<typename ... Ts>
using Action = std::function < void(Ts...) >;

which allows to define callback functions with any number of parameters. Yould could do it similarly with std::bind, but this way the code is cleaner and easier to read.

like image 51
Mike Lischke Avatar answered Nov 14 '22 22:11

Mike Lischke