Const-ness в качестве аргумента шаблона
У меня две структуры:
// ----- non-const -----
struct arg_adapter
{
EArgType type; // fmtA, fmtB, ...
union
{
TypeA * valueA;
TypeB * valueB;
// ... more types
}
arg_adapter(TypeA & value) : type(fmtA), valueA(&value) {}
arg_adapter(TypeB & value) : type(fmtB), valueB(&value) {}
// ...
}
// ----- const version -----
struct const_arg_adapter
{
EArgType type; // fmtA, fmtB, ...
union
{
TypeA const * valueA;
TypeB const * valueB;
// ... more types
}
arg_adapter(TypeA const & value) : type(fmtA), valueA(&value) {}
arg_adapter(TypeB const & value) : type(fmtB), valueB(&value) {}
// ...
}
Они должны использоваться в таких методах, как:
Convert(const_arg_adapter from, arg_adapter to)
Есть несколько TypeX (около 5, может стать больше), большинство из них примитивны. Это делается для того, чтобы не поддерживать разные прототипы.
Теперь мой вопрос; -)
Есть ли способ сделать константу параметром шаблона?
Моя цель - поддерживать только одну структуру, т.е.
template <Qualifier CONSTNESS>
struct arg_adapter_t
{
...
CONSTNESS TypeA * valueA;
...
}
Ответы
Ответ 1
Вы можете заставить его принять metafunction, и вы можете применить любое преобразование, которое вам нравится
template<template<typename> class F>
struct arg_adapter
{
EArgType type; // fmtA, fmtB, ...
union
{
typename F<TypeA>::type * valueA;
typename F<TypeB>::type * valueB;
// ... more types
};
arg_adapter(typename F<TypeA>::type & value) : type(fmtA), valueA(&value) {}
arg_adapter(typename F<TypeB>::type & value) : type(fmtB), valueB(&value) {}
// ...
};
typename arg_adapter<boost::add_const> const_adapter;
typename arg_adapter<boost::mpl::identity> nonconst_adapter;
Или примите класс metafunction, чтобы получить большую гибкость (в том числе возможность сделать F
аргументы по умолчанию, не известные вашему arg_adapter
и т.д.
template<typename F>
struct arg_adapter
{
EArgType type; // fmtA, fmtB, ...
union
{
typename apply<F, TypeA>::type * valueA;
typename apply<F, TypeB>::type * valueB;
// ... more types
};
arg_adapter(typename apply<F, TypeA>::type & value) : type(fmtA), valueA(&value) {}
arg_adapter(typename apply<F, TypeB>::type & value) : type(fmtB), valueB(&value) {}
// ...
};
typename arg_adapter< lambda< boost::add_const<_> >::type > const_adapter;
typename arg_adapter< lambda< boost::mpl::identity<_> >::type > nonconst_adapter;
Ответ 2
Я просто споткнулся о еще лучшем способе, используя идеал идеолога выбора Alexandrescu в "Modern С++ 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) {}
// ...
}
Вы можете использовать typedef для удобства:
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> > {};
Ответ 3
Возможно, я этого не понял, но почему вы не можете использовать
Convert(**const** arg_adapter from, arg_adapter to)
Объявить typedef для упрощения задания