I'm trying to write a rather simple class that takes a function, some arguments, and can execute the function with the arguments at a later time.
Currently, this is my code:
template<typename R, typename... Args>
class Delayed
{
public:
using FunctionT = std::function<R(Args...)>;
Delayed(FunctionT func, Args... args) : func(func), args(std::forward<Args>(args)...)
{
}
private:
FunctionT func;
std::tuple<Args...> args;
};
int main()
{
std::function<double(double)> doubleMe = [](double x) { return x * 2.0; };
//Works
Delayed<double, double> delayed1(doubleMe, 2.0);
//Doesn't work
Delayed<double(double)> delayed2(doubleMe, 2.0);
}
The problem is that when I pass double(double)
as an argument, instead of R
being double
and Args
being double
, it passes double(double)
to R
and nothing to Args
.
According to cppreference , the template arguments for std::function
is template< class R, class... Args >
. So if I give it A(B,C)
, it will pass A
for the argument R
and B,C
for the variadic argument Args
. But when I pass that to my class it passes A(B,C)
for R
and passes nothing for the variadic argument Args
.
How is this function syntax supposed to be used and why does it work for std::function
but not my class?
So if I give it
A(B,C)
, it will passA
for the argumentR
andB,C
for the variadic argumentArgs
.
Yes, but not for the reasons you think. If you look closely, you'll see that std::function
partially specializes for any function type:
template<typename R, typename... Args>
class function<R(Args...)>;
// ^^^^^^^^^^^^
You can imagine this as very primitive pattern matching. If you instantiate function
with int(int, double)
, then it makes sense that R
is int
, and Args
is int, double
. If a (partial) specialization is a better match than the catch-all generic primary template, then it is chosen, which is what happens here.
Remember: double(double)
is a type, it's a function. There aren't any special rules involving it. So, in your case, you would do this:
template<typename R, typename... Args>
class Delayed<R(Args...)> : public Delayed<R, Args...> {
// ^^^^^^^^^^^^
// partially specialize to decompose function types
// We need to inherit constructors (only).
using Delayed<R, Args...>::Delayed;
};
Hope it clears up the confusion.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.