C++ 常量作为模板参数
我有两个结构:C++ 常量作为模板参数,c++,templates,qualifiers,C++,Templates,Qualifiers,我有两个结构: // ----- non-const ----- struct arg_adapter { EArgType type; // fmtA, fmtB, ... union { TypeA * valueA; TypeB * valueB; // ... more types } arg_adapter(TypeA & value) : type(f
// ----- 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;
...
}
模板
结构参数适配器
{
...
常数A型*A值;
...
}
也许我没有得到它,但为什么你不能使用它呢
Convert(**const** arg_adapter from, arg_adapter to)
声明一个typedef以简化作业您可以让它接受,并且可以应用任何您喜欢的转换
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;
我刚才在Alexandrescu的《现代C++设计》中用了一个更好的方式来选择一个更好的方法: 这是类型选择器:
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; }
模板
结构选择{typedef T Result;}
模板
结构选择{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) {}
// ...
}
模板
结构参数适配器
{
//将A和B定义为常量或非常量
typedef typename Select::结果A;
typedef typename Select::结果B;
EArgType type;//fmtA、fmtB。。。
联盟
{
A*valueA;//这是常量TypeA*或常量TypeA*,具体取决于
//您可以选择isConst模板参数
B*价值B;
//…更多类型
}
arg_适配器(A&value):类型(fmtA),值A(&value){}//此处与ref相同
arg_适配器(B和值):类型(fmtB),值B和值{}
// ...
}
为了方便起见,您可以使用typedefs:
struct nonconst_adapter : public arg_adapter<false> {};
struct const_adapter : public arg_adapter<true> {};
struct noncst_适配器:公共arg_适配器{};
结构常量适配器:公共参数适配器{};
这是我使用简单类型特征的老答案:
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> > {};
模板
结构参数适配器
{
typedef typename TypeTraits::T;
空条(TA){…}//按值/引用
空条(T*a){…}//通过指针
}
模板
结构非标准特性{
类型定义K T;
}
模板
结构常数特性{
类型定义常数K T;
}
模板
结构非ST_适配器:公共arg_适配器{};
模板
结构常量适配器:公共参数适配器{};
“指向的对象的常量是模板参数的一个属性。”这与常量指针无关。我需要调用Convert with(常量TypeA&,TypeB&)
,而且arg_适配器没有用于consttypea&
的构造函数。也许添加一些typedef
可以避免在C++0x中重复typename apply::type
太多:)@Matthieu,我们可以说apply&
。我会喜欢模板别名:)我也会,我也会:)我急切地等待模板别名和可变模板,只是想知道哪个编译器会先编译:/谢谢你的回复-它很好地说明了Johannes使用boost的解决方案的功能。--我最终没有使用它,因为所有typedef的代码量都是一样的(在添加的情况下,其他一些地方无论如何都必须更新)。尽管如此,我还是对TMP.FYI更加自信了——从C++11标准开始,您不再需要定义自己的Select,因为它正是这样做的。
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> > {};