简体   繁体   中英

Forward variadic function arguments to variadic function using C++11

I want to forward calls to a library which has a variadic method. The simplest example I could come up with to replicate the problem is this:

void Bar(int useless, ...)
{
  //Does something
}

template<typename... Args>
void Foo(int useless, Args... args)
{
  Bar(useless, args...);
}

As you can see, I have had a go. However, even though this compiles, it seems to cause the stack to have a wobbler and I see errors on application exit. I can understand from the compilers point of view that this solution is problematic.

I am unsure how to get this working, or whether it is even possible to get this working. I have seen some people suggest using the "indices trick" in similar situations but I have not been able to get it working on this particular occasion.

Any help appreciated!

The approach you are taking is very sane, safe and sound by itself. For example, the below program is using variadic template arguments and forwards them to std::printf() , which is a C-style function that accepts variable number of arguments:

#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]);
}

The problem with undefined behavior and possibly stack corruption is caused by something else. In C++, this is most likely caused by passing non-POD types though C's variable argument list (ie passing std::string to printf() can do this).

Unfortunately, compiler extensions like "format attribute" won't help here. But compiler might warn you about non-POD types. For example, call my_printf() with std::string and you will be rewarded with a warning similar to this:

./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)...);

                                          ^

Of course, there could be something else going on that compiler won't be able to catch for you. Unfortunately, there is no better way than to debug your program and see what exactly is causing it to crash.

Since you are entering dark waters of C and unsafe arguments passing, debugger is your friend here, and I'd also recommend you use Valgrind - it is very helpful catching things like that.

Hope it helps. Good Luck!

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM