см. Пример ниже в реальном времени: https://onlinegdb.com/Hkg6iQ3ZNI
#include <iostream>
#include <utility>
#include <type_traits>
class A
{
public:
A(int v=-10):v_(v){}
void print()
{
std::cout << "called A: " << v_ << std::endl;
}
private:
int v_;
};
void f(int v)
{
std::cout << "called f: " << v << std::endl;
}
template<typename T,typename ... Args>
void run(A&& a,
T&& t,
Args&& ... args)
{
a.print();
t(std::forward<Args>(args)...);
}
template<typename T,typename ... Args>
void run(T&& t,
Args&& ... args)
{
run(A(),
std::forward<T>(t),
std::forward<Args>(args)...);
}
int main()
{
int v_function=1;
int v_a = 2;
run(f,v_function);
return 0;
}
Приведенный выше код компилируется, запускается и печатается (как и ожидалось):
называется A : -10
вызывается f: 1
, но если основная функция изменяется на:
int main()
{
int v_function=1;
int v_a = 2;
run(f,v_function);
// !! added lines !!
A a(v_a);
run(a,f,v_function);
return 0;
}
, то компиляция завершается с ошибкой:
main. cpp: 30: 6: ошибка: нет совпадения для вызова '(A) (void (&) (int), int &)'
t (std :: forward (аргументы) ...);
~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
, что, по-видимому, указывает на то, что даже когда экземпляр A передается в качестве первого аргумента, вызывается функция перегрузки
void(*)(T&&,Args&&...)
, а не
void(*)(A&&,T&&,Args&&...)