ИМХО, как правило, лучшим решением является определение структуры для передачи параметров.
Но вы заявляете, что не хотите этого, вам нужна нормальная запись.
В этом случае библиотека Boost Parameters является самой простой.
Если вы не можете использовать Boost, вы можете сделать это самостоятельно.
Тем не менее, количество кода для DIY-решения типа Boost Parameters, квадратичного по количеству аргументов, хотя квадратичное намного лучше, чем факториального, оно все еще своего рода запретительно & hellip; Я приведу пример кода ниже. Основная идея состоит в том, чтобы идентифицировать аргументы по типам, а затем они легко сортируются во время компиляции.
template< class Type >
struct Pointer
{
Type const* p_;
Pointer( Type* p = 0 ): p_( p ) {}
};
template< class Type, class Args >
Type const* pointer( Args const& args )
{
return static_cast< Pointer< Type > const& >( args ).p_;
}
template< class Type, class Args >
Type const*& pointerRef( Args& args )
{
return static_cast< Pointer< Type >& >( args ).p_;
}
//-----------------------------------------------------
class A {}; class B {}; class C {};
A const a_def; B const b_def; C const c_def;
void foo( A const* pa, B const* pb, C const* pc )
{
A const& a = (pa? *pa : a_def);
B const& b = (pb? *pb : b_def);
C const& c = (pc? *pc : c_def);
// Whatever, use a b c here.
}
struct FooArgs
: Pointer< A >
, Pointer< B >
, Pointer< C >
{};
void foo( FooArgs const& args )
{
foo( pointer< A >( args ), pointer< B >( args ), pointer< C >( args ) );
}
void foo()
{
foo( FooArgs() );
}
template< class T1 >
void foo( T1 const& v1 )
{
FooArgs args;
pointerRef< T1 >( args ) = &v1;
foo( args );
}
template< class T1, class T2 >
void foo( T1 const& v1, T2 const& v2 )
{
FooArgs args;
pointerRef< T1 >( args ) = &v1;
pointerRef< T2 >( args ) = &v2;
foo( args );
}
template< class T1, class T2, class T3 >
void foo( T1 const& v1, T2 const& v2, T3 const& v3 )
{
FooArgs args;
pointerRef< T1 >( args ) = &v1;
pointerRef< T2 >( args ) = &v2;
pointerRef< T3 >( args ) = &v3;
foo( args );
}
int main()
{
foo( B() );
}
Как уже упоминалось, эта вещь DIY была бы моим последним выбором.
Я пропустил проверку ошибок в этом примере кода. Например, код не должен компилироваться, если два или более фактических аргумента имеют одинаковый тип. Я также опустил обобщение на случай, когда формальные аргументы не все одного типа. Эти пропущенные вещи способствуют большей сложности. Так что, если вышеперечисленное кажется непомерным, подумайте, как оно выглядит в «полной версии», так сказать.
Для случая, когда вам нужны строго типизированные необязательные аргументы, например, для конструкторы в иерархии классов, см. мой блог: "Как сделать типизированные необязательные аргументы в C ++ 98" .
Приветствия & hth.,