void av(va_list args)
{
// do stuff using va_arg macro
}
void a(...)
{
va_list args;
va_start(args, 0); // тут не уверен что ноль,
// возможно, работает только для функций с 1+ аргументами,
// т.е. должен быть хоть один именованный аргумент
av(args);
}
void b(...)
{
va_list args;
va_start(args, 0);
av(args);
}
Здравствуйте, rising_edge, Вы писали:
_>Здравствуйте, unreg_flex, Вы писали:
_>>почти уверен что никак, но все же ...
_>А поиском по сайту пробовали пользоваться? Тема обсуждалась неоднократно.
Пользовался поиском по мсдну, как бэ мне показалось что там вероятнее это найти, однако на такое:
void av(va_list args)
{
// do stuff using va_arg macro
}
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
Здравствуйте, achp, Вы писали:
A>Здравствуйте, alexeiz, Вы писали:
A>>Хаха, а вот и нет! А аргументы кто форвардить будет? И возвращаемое значение было бы неплохо вывести тоже. A>>
Здравствуйте, alexeiz, Вы писали:
A>А аргументы кто форвардить будет? A>
A>template <typename ... Args>
A>auto b(Args && ... args) -> decltype(a(std::forward<Args>(args) ...))
A>{
A> return a(std::forward<Args>(args) ...);
A>}
A>
Вот! Тебя-то мне и надо! Хоть ты сможешь по-человечески растолковать, что же делает std::forward, зачем ей явно указывать шаблонный параметр и зачем она вообще нужна?
Roman Odaisky:
RO>что же делает std::forward, зачем ей явно указывать шаблонный параметр и зачем она вообще нужна?
Порой возникает задача: передать аргументы некоей функции-оболочки другой функции (возможно, перегруженной) так, чтобы результат вызова функции-оболочки был практически идентичен вызову этой другой функции с теми же самыми аргументами.
The general form of the forwarding problem is that in the current language,
For a given expression E(a1, a2, ..., an) that depends on the (generic) parameters a1, a2, ..., an, it is not possible to write a function (object) f such that f(a1, a2, ..., an) is equivalent to E(a1, a2, ..., an).
В общем случае эта проблема остаётся неразрешимой и в C++0x (см. Perfect Forwarding Failure Cases), но rvalue-ссылки позволяют значительно приблизиться к идеалу.
Аргумент функции — это по определению какое-то выражение. Каждое выражение обладает следующими свойствами:
1) тип,
2) принадлежность к lvalues или rvalues,
3) принадлежность к битовым полям,
4) принадлежность к константным выражениям.
Возможно, есть ещё что-то. Идеальная пересылка аргумента подразумевает как минимум сохранение этих четырёх свойств. С помощью rvalue-ссылок C++0x предоставит возможность сохранять два из них:
1) тип,
2) принадлежность к lvalues (иногда именуемая как lvalueness).
Для сохранения типа ничего особенного делать не нужно, а вот чтобы сохранить lvalueness, приходится выполнять кое-какое преобразование. Прежде всего, нужно отметить следующее:
N3035 — 5/6:
If an expression initially has the type “rvalue reference to T” (8.3.2, 8.5.3), the type is adjusted to “T” prior to any further analysis, and the expression designates the object or function denoted by the rvalue reference. If the expression is the result of calling a function, whether implicitly or explicitly, it is an rvalue; otherwise, it is an lvalue.
5.2.9/1:
The result of the expression static_cast<T>(v) is the result of converting the expression v to type T. If T is an lvalue reference type, the result is an lvalue; otherwise, the result is an rvalue.
Как видно, именованные ссылки — всегда lvalues. Это значит, что если мы запишем так:
template <class T>
void f(T &&t)
{ E(t); }
то не получим адекватной пересылки rvalue (аргументом для E всегда будет lvalue):
Для пересылки аргумента с сохранением принадлежности к lvalues/rvalues нам нужно получать из t rvalue-выражение, когда аргументом f передаётся rvalue. Этим и занимается std::forward.
struct A {};
void E(A &&) { std::cout << "E(A &&)\n"; }
void E(A const &) { std::cout << "E(A const &)\n"; }
template <class T>
void f(T &&t)
{ E(std::forward<T>(t)); }
int main()
{
A a;
E(a); // calls E(A const &)
f(a); // calls E(A const &)
// T is deduced to be "lvalue reference to A"
// f<A &>'s function parameter is "lvalue reference to A"
E(A()); // calls E(A &&)
f(A()); // calls E(A &&)
// T is deduced to be "A"
// f<A>'s function parameter is "rvalue reference to A"
}
Выведенный шаблонный аргумент для параметра T зависит от принадлежности аргумента, переданного в f, к lvalue: если аргумент — lvalue типа A, то шаблонный аргумент, выведенный для T, будет "lvalue reference to A"; если аргумент — rvalue типа A, то шаблонный аргумент, выведенный для T, будет просто "A" (см. 14.9.2.1/3). В первом случае попытка формирования ссылки на ссылку приводит к сокращению ссылок (см. 14.4.1/4), т.е. rvalue-ссылка на lvalue-ссылку типа A превращается в lvalue-ссылку типа A. Приведу выдержки из правил:
14.9.2.1/1:
Template argument deduction is done by comparing each function template parameter type (call it P) with the type of the corresponding argument of the call (call it A) as described below.
14.9.2.1/3:
If P is an rvalue reference to a cv-unqualified template parameter and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction. [ Example:
template <typename T> int f(T&&);
int i;
int j = f(i); // calls f<int&>(i)template <typename T> int g(const T&&);
int k;
int n = g(k); // calls g<int>(k)
—end example ]
14.4.1/4:
If a template-argument for a template-parameter T names a type that is a reference to a type A, an attempt to create the type “lvalue reference to cv T” creates the type “lvalue reference to A,” while an attempt to create the type “rvalue reference to cv T” creates the type T [ Example:
template <class T> class X {
void f(const T&);
void g(T&&);
};
X<int&> x1; // X<int&>::f has the parameter type int&
// X<int&>::g has the parameter type int&
X<const int&&> x2; // X<const int&&>::f has the parameter type const int&
// X<const int&&>::g has the parameter type const int&&
—end example ]
Впрочем, следует ожидать, что в будущем концепция lvalue и rvalue претерпит некоторые изменения — см. N3030.
Re[3]: Вызов функции с переменным числом параметров
M>Выведенный шаблонный аргумент для параметра T зависит от принадлежности аргумента, переданного в f, к lvalue: если аргумент — lvalue типа A, то шаблонный аргумент, выведенный для T, будет "lvalue reference to A"; если аргумент — rvalue типа A, то шаблонный аргумент, выведенный для T, будет просто "A" (см. 14.9.2.1/3).
Ага. Т. е., если бы std::forward не принимала явно тип T, то ей было бы никак не узнать, на lvalue ли ссылается t, потому что t во всех отношениях похожа на обычную &-ссылку?
И еще, при A const ca; f(ca); будет T = A const &? Тогда при template <class X> void r(X &), что ли, можно вызывать r(ca) и получить X = A const? Как-то странно смотрится.