[petsc-dev] Preprocessor hell: #define VecType

Karl Rupp rupp at mcs.anl.gov
Sun Sep 30 08:46:15 CDT 2012


Hi,

 >>> ^^^ Note that this const is superfluous.
>> Why is it superfluous?  Isn't the second argument type const char* const this way?
>>
>> It's superfluous for the same reason we don't "set" by passing "const PetscInt". The const is irrelevant to the caller. All it means is that the implementation doesn't change the *its* copy (pass by value) and even that isn't type checked with respect to the public declaration. It's just clutter and suggests that the person who wrote it doesn't understand types.
>
>    Which clearly I don't :-(
>
>     So do we just go with typedef const char* VecType   and then all signatures are  VecType?

yes, Jed is absolutely right on that. The important thing to keep in 
mind here is that typedef is atomic, i.e. it is not a 'string 
replacement' as opposed to what the C preprocessor does.

Example:
   #define VecType char*
   int Set(const VecType)
expands to
   int Set(const char*)

However, with
   typedef const char* VecType
   int Set(const VecType)
there is no immediate string replacement, i.e. it is NOT the same as
   int Set(const const char*)
with the compiler ignoring one of the const keywords. Instead, denoting 
the precedence using brackets, the type passed to the Set() is
   const {const char*}
which is a const copy to a const char*. Now, as 'const char*' is copied 
when passed to the function anyways, the first 'const' is superfluous as 
Jed pointed out. As a consequence, we can simply use
   Set(VecType);
   Get(VecType*);
which is pretty much the standard prototype for any pair of 
Getter/Setter and also the way arguments of type PetscInt are handled.

In conclusion, we have not only eliminated the preprocessor magic, we 
are also able to provide a cleaned-up interface for XYZSetType() and 
XYZGetType(). Thanks, Barry, for making the decision in favor of a 
typedef :-)

Best regards,
Karli





More information about the petsc-dev mailing list