我想将调用转发到具有可变方法的库。我能想出的最简单的例子是:
void Bar(int useless, ...)
{
//Does something
}
template<typename... Args>
void Foo(int useless, Args... args)
{
Bar(useless, args...);
}
正如你所看到的,我已经走了。但是,即使这个编译,它似乎导致堆栈有一个摇摆,我看到应用程序退出时出错。从编译器的角度来看,我可以理解这个解决方案存在问题。
我不确定如何使这个工作,或者是否有可能使这个工作。我见过有些人建议在类似情况下使用“指数技巧”,但我无法在这个特殊场合使用它。
任何帮助表示赞赏!
答案 0 :(得分:9)
你采取的方法本身非常理智,安全和健全。例如,下面的程序使用可变参数模板参数并将它们转发到std::printf()
,这是一个接受可变数量参数的C风格函数:
#include <utility>
#include <cstdio>
template <unsigned int S, typename ...T>
void my_printf(const char (&fmt)[S], T&&... args) {
std::printf(fmt, std::forward<T>(args)...);
}
int main(int argc, const char* argv[]) {
my_printf("Hello, %s!\n", "World!");
my_printf("I will count to %u...\n", 10);
for (int i = 0; i < 10; ++i)
my_printf("%s %s %u\n", "...", "and", i + 1);
my_printf("And here are my arguments :)\n");
for (int i = 0; i < argc; ++i)
my_printf("argv[%u] == %s\n", i, argv[i]);
}
未定义行为和可能的堆栈损坏的问题是由其他原因引起的。在C ++中,这很可能是由于通过C的变量参数列表传递非POD类型(即将std::string
传递给printf()
可以做到这一点)。
不幸的是,像"format attribute"这样的编译器扩展在这里无济于事。但编译器可能会警告您非POD类型。例如,使用my_printf()
致电std::string
,您将收到与此类似的警告:
./test.cc:7:46: error: cannot pass objects of non-trivially-copyable type ‘class std::basic_string<char>’ through ‘...’
std::printf(fmt, std::forward<T>(args)...);
^
当然,可能还有其他东西会发生,编译器将无法为您捕获。不幸的是,没有比调试程序更好的方法,看看究竟是什么导致程序崩溃。
由于您正在进入C的黑暗水域并且不安全的参数传递,调试器在这里是您的朋友,我还建议您使用Valgrind - 这样做很有帮助。
希望它有所帮助。祝你好运!