Я только что наткнулся на еще лучший способ, используя идею выбора типа, представленную Александреску в "Современном C ++ Design":
Это селектор типа:
template<bool flag, typename T, typename U>
struct Select { typedef T Result; }
template<typename T, typename U>
struct Select<false, T, U> { typedef U Result; }
Ваш класс будет выглядеть так:
template<bool isConst>
struct arg_adapter
{
// define A and B as const or non-const
typedef typename Select<isConst, const TypeA, TypeA>::Result A;
typedef typename Select<isConst, const TypeB, TypeB>::Result B;
EArgType type; // fmtA, fmtB, ...
union
{
A * valueA; // this is either const TypeA* oder TypeA* depending on
// your choice of the isConst template parameter
B * valueB;
// ... more types
}
arg_adapter(A & value) : type(fmtA), valueA(&value) {} // same here with ref
arg_adapter(B & value) : type(fmtB), valueB(&value) {}
// ...
}
Вы можете использовать typedefs для удобства:
struct nonconst_adapter : public arg_adapter<false> {};
struct const_adapter : public arg_adapter<true> {};
Это был мой старый ответ с использованием простых черт типа:
template<typename TypeTraits>
struct arg_adapter
{
typedef typename TypeTraits::T T;
void bar(T a) { ... } // by value/reference
void bar(T* a) { ... } // by pointer
}
template<typename K>
struct NonConstTraits {
typedef K T;
}
template<typename K>
struct ConstTraits {
typedef const K T;
}
template<typename K>
struct nonconst_adapter : public arg_adapter<NonConstTraits<K> > {};
template<typename K>
struct const_adapter : public arg_adapter<ConstTraits<K> > {};