chema989
chema989

Reputation: 4182

How to transform a variadic template argument to another types for calling another function?

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

Answers (2)

max66
max66

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

Barry
Barry

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

Related Questions