In this answer what I really wanted to do is define a typename
in my template parameters which could be used in the cast and return.
So this:
template <typename T>
typename std::enable_if<sizeof(unsigned char) == sizeof(T), unsigned char>::type caster(T value){ return reinterpret_cast<unsigned char&>(value); }
Would become this:
template <typename T, typename R = std::enable_if<sizeof(unsigned char) == sizeof(T), unsigned char>::type >
R caster(T value){ return reinterpret_cast<R&>(value); }
This works and behaves as desired for a single template specialization, but say that I add another specialization:
template <typename T, typename R = std::enable_if<sizeof(short) == sizeof(T), short>::type>
R caster(T value){ return reinterpret_cast<R&>(value); }
Now I get an error:
error C2995: 'R caster(T)' : function template has already been defined
Is there a way to convince the compiler that only one of these specializations will actually build for any given call?
No, there isn't. Template default arguments are just that, defaults. Any user could call
caster<short, short>
, which would match both overloads.However, it would be possible to add more dummy arguments.
(Also note the added
typename
.)However, since all bodies are identical, I probably wouldn't go with overloads.
A final note: this use of
reinterpret_cast
is a violation of the aliasing rules. However, that's easily fixed:It seems that the best solution here may be to use a slew of
conditional
s, which would prevent me from having to fool with template specializations:My apologies to the reader cause it's like reading nested ternaries. However I'm currently unaware of a cleaner way to handle this.
This sadly still doesn't prevent the user from stomping on all my defaulting by providing his own second template parameter as mentioned by hvd.
EDIT:
I've asked another question here which has a solution that doesn't require placing the
typename
in the template definition and doesn't require declaring the type twice.