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