2016-06-06 9 views
8

Ostatnio spotykam przykry problem, że chcę, aby określić funkcje tak:Jak korzystać z listy parametrów o zmiennej długości tylko z jednym parametrem referencyjnym?

std::string my_sprintf(const char* format, ...) 
{ 
    va_list args; 
    va_start(args, format); 
    ... 
} 
std::string my_sprintf(const std::string& format, ...) 
{ 
    va_list args; 
    va_start(args, format); // error 
    ... 
} 

Ale wydaje wartość odniesienia nie może być ostatni parametr przy użyciu zmiennej długości listy parametrów.

Czy jest to sposób, że mogę pozwolić użytkownikowi użyć std :: string jako ciąg formatu?

Może czynniki lub coś innego, co wykrywa std :: string i konwertuje go jako c_str(), ale nie wiem jak sobie poradzić z poniższą listą parametrów o zmiennej długości.

Edytuj: Nie używam szablonu variadic, ponieważ używam vsprintf wewnątrz. Może unikniesz używania vsprintf i używanie std :: stringstream jest opcją?

+1

[tag: c] nie jest [tag: C++]. –

+0

@ iharob my bad: P –

+0

C++ sposób na użycie 'printf' jest użycie szablonów variadic [jak tutaj] (http://stackoverflow.com/questions/17671772/c11-variadic-printf-performance) – justanothercoder

Odpowiedz

6

Zachowanie to niezdefiniowana: Zobacz C++ Standard 18.10/3 (dla C++ 11 i C++ 14) lub cppreference.com: Variadic Arguments.

Zasadniczo można używać tylko typów dostępnych w języku C z wartością va_start, chociaż wyjątek dotyczy typu std::nullptr_t.

+3

Są one również nazywane ** POD ** * Zwykłe stare dane *, [czytaj to] (http://stackoverflow.com/questions/146452/what-are-pod-types-in-c). –

+0

Wiem doskonale, że jest to zabronione, ale po prostu pytam, czy istnieje sposób, aby to zrobić. –

+0

Nie z 'va_start', nie. Ale nie ma powodu, dla którego nie mógłbyś użyć szablonów * z wariadami *. Lub po prostu głęboko skopiować ciąg. Etap i/o twojej funkcji będzie wąskim gardłem, a nie głęboką kopią. – Bathsheba

2

W C++, tak aby przekazać „nieznany” argumentów jest użycie zmiennej liczbie argumentów szablonu:

template <typename ... Ts> 
std::string my_sprintf(const std::string& format, Ts&&...args) 
{ 
    return my_sprintf(format.c_str(), std::forward<Ts>(args)...); 
} 

i wam wersję z const char* prawdopodobnie powinien być również o zmiennej liczbie argumentów szablon, za pomocą sprintf zamiast vsprintf.

+0

@ user2079303: Huh? Wysyła dalej do przeładowania "const char *" ... – MFH

+0

@ user2079303: W przypadku obu wersji variadic działa [Demo] (http://coliru.stacked-crooked.com/a/649e95afbeee69b4). Jednak w przypadku wielokropka jest on niejednoznaczny i wymaga zmiany nazwy na obejście tego problemu. – Jarod42

+0

@ Jarod42 oh, racja. Próbowałem zrozumieć ten kod w próżni - nie zdając sobie sprawy, że istnieje przeciążenie. Przepraszam za hałas. – user2079303

Powiązane problemy