Reputation: 4182
Function f
receives arguments that can be transform to Wrapper
using transform
function and it must call f2
. f2
receives a varidic number of Wrapper like arguments.
template <typename T>
Wrapper transform(T&& value) {
return Wrapper(std::forward<T>(value));
}
template <typename... Args>
Wrapper f2(Args&&... args) {
// All arguments must be Wrappers
// More code
}
template <typename... Args>
Wrapper f(Args&&... args) {
// Arguments can be transform to Wrapper using a transform function.
return f2( /* For each arg in args -> transform(std::forward<Args>(args)...)*/ ); // Problem!
}
The normal is to transform the parameters before and calling directly f2
but I do not want to expose transform
function to public.
Is there a way to achieve this, without expose transform
function?
Upvotes: 1
Views: 2167
Reputation: 66230
Is there a way to achieve this, without expose transform function?
What about using a lambda function?
template <typename... Args>
Wrapper f(Args&&... args)
{
static const auto tf = [](auto && value)
{ return Wrapper(std::forward<decltype(value)>(value)); };
return f2( tf(std::forward<Args>(args)) ... );
}
Observe that you tagged C++14 so you can use auto
arguments in lambda functions
Another solution (also C++11) can be the use of a functor (fc
instead f
)
class fc
{
private:
template <typename T>
Wrapper transform (T && value)
{ return Wrapper(std::forward<T>(value)); }
public:
template <typename... Args>
Wrapper operator() (Args&&... args)
{ return f2( transform(std::forward<Args>(args)) ... ); }
};
But the use is slightly different: you can create a temporary object (but using another couple of parentheses
fc()(1, "abc", 2.3f);
or you can create an object of type fc
and use it as a function
fc f0;
f0(1, "abc", 2.3f);
Upvotes: 1
Reputation: 304112
Pack expansion can apply to arbitrarily complex expressions. In here:
return f2( /* For each arg in args -> transform(std::forward<Args>(args)...)*/ ); // Problem!
The problem is that you're expanding inside of transform
... that's the equivalent of writing f2(transform(a0, a1, a2, ..., aN))
. Hopefully it's clear why that's wrong. You want the expression you're expanding to include the transform
. That is:
return f2(transform(std::forward<Args>(args))...);
Which expands into f2(transform(a0), transform(a1), ..., transform(aN))
.
Upvotes: 2