I needed to make a function that, after starting, pointed to a function with variable arguments and some fixed arguments and could not make it work on Visual Studio 2013. I assumed that perhaps Visual Studio 2013 is missing something that often happens and made a minimal example that did what I needed and tried it against gcc and clang. And I have all different results for all three compilers. Therefore, the issues that I would like to solve are the following:
- Is my example valid? If not what am I doing wrong?
- If my example is valid, any hints about the behavior of gcc and clang (allows you to read msvc due to the black box)?
Example:
#include <iostream>
struct foo
{
void work(int first, int second, int third)
{
std::cout << "0: " << first << ",1: " << second << ",2: " << third << std::endl;
}
void work_with_double(double first, int second, int third, int fourth)
{
std::cout << "0: " << first << ",1: " << second << ",2: " << third << ",3: " << fourth << std::endl;
}
};
template<typename ... argument_types>
void invoke_foo(foo* instance, int first, int second, int third, void (foo::*method)(argument_types ... arguments, int, int, int), argument_types ... arguments)
{
(instance->*method)(arguments ..., first, second, third);
}
int main(int argc, char** argv)
{
foo instance;
invoke_foo(&instance, 1, 2, 3, &foo::work);
invoke_foo<>(&instance, 1, 2, 3, &foo::work);
invoke_foo(&instance, 1, 2, 3, &foo::work_with_double, 1.0);
invoke_foo<double>(&instance, 1, 2, 3, &foo::work_with_double, 1.0);
return 0;
}
, Visual Studio 2015 ( )
invoke_foo - , Visual Studio 2015.
#include <iostream>
#include <memory>
struct foo
{
void work(int first, int second, int third, int fourth, int fifth, int sixth, int seventh, int eight)
{
std::cout << "0: " << first << ",1: " << second << ",2: " << third << std::endl;
}
void work_with_double(double firstExtra, int first, int second, int third, int fourth, int fifth, int sixth, int seventh, int eight)
{
std::cout << "0: " << first << ",1: " << second << ",2: " << third << ",3: " << fourth << std::endl;
}
};
struct bar
{
};
struct wrapper
{
template <typename T> struct non_deduced { using type = T; };
template <typename T> using non_deduced_t = typename non_deduced<T>::type;
template<typename ... argument_types>
std::shared_ptr<bar> invoke_foo(int first, int second, int third, int fourth, int fifth, int sixth, int seventh, int eight, void (foo::*method)(non_deduced_t<argument_types>... arguments, int, int, int, int, int, int, int, int), argument_types ... arguments)
{
(foo_.get()->*method)(arguments ..., first, second, third, fourth, fifth, sixth, seventh, eight);
return nullptr;
}
std::unique_ptr<foo> foo_ = std::move(std::unique_ptr<foo>(new foo));
};
int main(int argc, char** argv)
{
wrapper instance;
instance.invoke_foo(1, 2, 3, 4, 5, 6, 7, 8, &foo::work);
instance.invoke_foo(1, 2, 3, 4, 5, 6, 7, 8, &foo::work_with_double, 1.0);
}