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> > {};