I have the following code:
#define RETURNS(...) -> decltype((__VA_ARGS__)) { return (__VA_ARGS__); }
template <typename This, typename... Args>
auto fun(This &&this_, Args&&... args) RETURNS(this_.fun(std::forward<Args>(args)...))
For better or worse, this allows me to use fun(o, args...) and o.f(args...) interchangeably. The difficulty in using this comes when using an initializer list as an argument. E.g.
fun(obj, {1, 2, 3}); // Where obj.fun eventually takes a std::vector<int>.
This fails due to a substitution error, so Clang says. Note, obj.fun({1, 2, 3}); works.
As I understand it from other questions, this is because initializer lists don't always play nicely with template argument deduction.
The closest I have to my desired syntax is by making the initializer list more explicit. To avoid verbosity, I have the following:
template <typename T> std::initializer_list<T> il(std::initializer_list<T> &&li) { return li; }
fun(obj, il({1, 2, 3}));
Is there a way of getting my desired syntax or closer to it?
Clang's error report in my test program is:
subst.cpp:16:5: error: no matching function for call to 'fun'
fun(x, {1, 2, 3});
^~~
subst.cpp:6:6: note: candidate template ignored: substitution failure [with This
= X &, Args = <>]: too few arguments to function call, single argument 'v'
was not specified
auto fun(This &&this_, Args&&... args) RETURNS(this_.fun(std::forward<Args>(args)...))
^ ~
{1,2,3}is not an expression, and it has no type that could be deduced.Args = <>), thus results in a substitution failure.iltake a variable number of arguments, to allow a syntax likefun(obj, il(1,2,3)). Alternatively, an uglyfun<some_type, std::initializer_list<int>>(obj, {1,2,3})is also possible (but not recommended).il(a, b, c, ...)tostd::initializer_list<A>{a, b, c, ...}. Sounds like a challenge.