Pregunta

If I have:

Class MyClass {
public:
    MyClass( /* args */ );
private:
    someType member0;
    someType member1;
    // ...
    someType memberN;
#if defined(FIRST_COMPILE_CONDITION)
    someType condition1Member0;
    someType condition1Member1;
    // ...
    someType condition1MemberN;
#endif
#if defined(SECOND_COMPILE_CONDITION)
    someType condition2Member0;
    someType condition2Member1;
    // ...
    someType condition2MemberN;
#endif
};

for some arbitrary number of compile conditions, is there a clean way to do the equivalent of this (especially for possibly multiple compile conditions), without putting some permanent member last?

MyClass::MyClass( /* args */ ) :
    member0( someValue ),
    member1( someValue ),
    // ...
    memberN( someValue ),
#if defined(FIRST_COMPILE_CONDITION)
    condition1Member0( someValue ),
    condition1Member1( someValue ),
    // ...
    condition1MemberN( someValue ),
#endif
#if defined(SECOND_COMPILE_CONDITION)
    condition2Member0( someValue ),
    condition2Member1( someValue ),
    // ...
    condition2MemberN( someValue ),
#endif
// ...
{
}

As the above will not compile under most conditions due to the trailing comma.

Edit to clarify:

It probably should be noted explicitly that someValue is intended to be a potentially independent, arbitrary value that may or may not depend on constructor arguments in each case used.

¿Fue útil?

Solución

You can put the comma before initializers:

MyClass::MyClass() :
     member0( someValue )
    ,member1( someValue )
    // ...
    , memberN( someValue )
#if defined(FIRST_COMPILE_CONDITION)
    ,condition1Member0( someValue )
    ,condition1Member1( someValue )
    // ...
    ,condition1MemberN( someValue )
#endif
// ...
{
}

Otros consejos

Personally, I try to avoid compiler directives as much as possible (except include guards) because they typically hide problems and reflect design issues.

One design issue we all face is windows/linux/mac specific code. There is little way around that to handle cross platform.

To handle this, I skip the compiler directives and address it at the Makefile/project level (depending on your tools). To do that here, you might:

  1. Add an init_conditional() method to the class and call it in the constructor
  2. Add class_init_....cpp files for each condition, each with a different implementation of the init_conditional()
  3. Have the make file decide which to compile and link in

Now, doing that is some work of its own, but is much cleaner in the code.

Note: This loses the protection of member-wise initialization but is a more general solution to the multiple-conditional-compilation problem.

I always use the following way to write initialisation:

MyClass::MyClass()
  : member0 ( some_value0 )
  , member1 ( some_value1 )
// etc
{}

it is the logically more correct way, as the comma separates a member from its predecessor, not the the next one.

I suppose that's the reason some people move the trailing comma so that it's in front of the next entry:

member0( someValue ),
    member1( someValue )
    // ...
    , memberN( someValue )
#if defined(FIRST_COMPILE_CONDITION)
    , condition1Member0( someValue )
    , condition1Member1( someValue )

But that's incredibly ugly.

Just reverse your comma logic:

MyClass::MyClass() :
    member0( someValue ),
    member1( someValue ),
    // ...
    memberN( someValue )
#if defined(FIRST_COMPILE_CONDITION)
    ,condition1Member0( someValue )
    ,condition1Member1( someValue )
    // ...
    ,condition1MemberN( someValue )
#endif
#if defined(SECOND_COMPILE_CONDITION)
    ,condition2Member0( someValue )
    ,condition2Member1( someValue )
    // ...
    ,condition2MemberN( someValue )
#endif
// ...
{
}

Note the removal of the comma after the first memberN

When you are able or allowed to use C++11 it becomes really easy

Class MyClass {
  public:
    MyClass();
  private:
    someType member0 = someValue;
    someType member1 = someValue;
    // ...
    someType memberN;
#if defined(FIRST_COMPILE_CONDITION)
    someType condition1Member0 = someValue;
    someType condition1Member1 = someValue;
    // ...
    someType condition1MemberN = someValue;
#endif
#if defined(SECOND_COMPILE_CONDITION)
    someType condition2Member0 = someValue;
    someType condition2Member1 = someValue;
    // ...
    someType condition2MemberN = someValue;
#endif
};

The real big advantage is, you don't have to care about multiple constructors. However, you may achieve this with other approaches, too.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top