簡體   English   中英

const-ness作為模板參數

[英]const-ness as template argument

我有兩個結構:

  // ----- 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,可能會變得更多),其中大多數都是原始的。 這是為了避免維護不同的原型。

現在我的問題;-)

有沒有辦法讓const-ness成為模板參數? 我的目標是只維護一個結構,即

template <Qualifier CONSTNESS>
struct arg_adapter_t
{
   ...
   CONSTNESS TypeA * valueA;
   ...
}

我剛剛在“現代C ++設計”中使用Alexandrescu的類型選擇ideom presentend,偶然發現了更好的方法:

這是類型選擇器:

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

您可以讓它接受元函數 ,您可以應用任何您喜歡的轉換

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;

或者接受元函數類以獲得更大的靈活性(包括使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;

也許我沒有得到它,但為什么你不能使用它

Convert(**const** arg_adapter from, arg_adapter to)

聲明typedef以簡化作業

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM