c++ missing - テンプレート引数としての定数




with for (4)

私は2つの構造体があります。

  // ----- 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;
   ...
}

Answers

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;

または、より柔軟性を高めるためにメタファンクションクラスを受け入れる( 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;

Alexandrescuによる「Modern 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) {}
  // ...
}

利便性のために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> > {};

たぶん私はそれを得なかったが、なぜあなたは使えないのか

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

仕事を簡単にするためにtypedefを宣言する


C ++ 17

C ++ 17 (今後の標準)は、 basic_stringテンプレートの概要を変更し、 data()非constオーバーロードを追加しdata()

charT* data() noexcept;

戻り値:[0、size()]の各iについて、p + i ==&演算子となるようなポインタp。

CharT const * from std::basic_string<CharT>

std::string const cstr = { "..." };
char const * p = cstr.data(); // or .c_str()

CharT * from std::basic_string<CharT>

std::string str = { "..." };
char * p = str.data();

C ++ 11

CharT const * from std::basic_string<CharT>

std::string str = { "..." };
str.c_str();

CharT * from std::basic_string<CharT>

C ++ 11以降、標準では次のように述べています。

  1. basic_stringオブジェクト内のchar-likeオブジェクトは、連続して格納されます。 つまり、任意のbasic_stringオブジェクトs&*(s.begin() + n) == &*s.begin() + nは、 n 0 <= n < s.size() nすべての値に対して0 <= n < s.size()
  1. const_reference operator[](size_type pos) const;
    reference operator[](size_type pos);

    戻り値: pos < size() *(begin() + pos)場合は*(begin() + pos) 、そうでない場合はCharT()型のオブジェクトへの参照。 参照される値は変更されないものとする。

  1. const charT* c_str() const noexcept;
    const charT* data() const noexcept;

    戻り値: [0,size()]iについてp + i == &operator[](i)となるようなポインタp。

非const文字ポインタを得るためには、可能な方法があります。

1. C ++ 11の連続したストレージを使用する

std::string foo{"text"};
auto p = &*foo.begin();

プロ

  • シンプルで短い
  • 高速(コピーを伴わない方法のみ)

短所

  • 最終的な'\0'は変更しないでください。非constメモリの一部である必要はありません。

2. std::vector<CharT>使用します。

std::string foo{"text"};
std::vector<char> fcv(foo.data(), foo.data()+foo.size()+1u);
auto p = fcv.data();

プロ

  • シンプル
  • 自動メモリ処理
  • 動的

短所

  • 文字列のコピーが必要です

3. Nがコンパイル時定数(かつ十分に小さい)であればstd::array<CharT, N>

std::string foo{"text"};
std::array<char, 5u> fca;
std::copy(foo.data(), foo.data()+foo.size()+1u, fca.begin());

プロ

  • シンプル
  • スタックメモリの処理

短所

  • 静的
  • 文字列のコピーが必要です

4.自動ストレージ削除によるRAWメモリ割り当て

std::string foo{ "text" };
auto p = std::make_unique<char[]>(foo.size()+1u);
std::copy(foo.data(), foo.data() + foo.size() + 1u, &p[0]);

プロ

  • メモリ占有量が少ない
  • 自動削除
  • シンプル

短所

  • 文字列のコピーが必要です
  • 静的(動的な使用にはさらに多くのコードが必要)
  • ベクトルまたは配列より少ない機能

5.手作業でのRAWメモリ割り当て

std::string foo{ "text" };
char * p = nullptr;
try
{
  p = new char[foo.size() + 1u];
  std::copy(foo.data(), foo.data() + foo.size() + 1u, p);
  // handle stuff with p
  delete[] p;
}
catch (...)
{
  if (p) { delete[] p; }
  throw;
}

プロ

  • 最大 'コントロール'

コン

  • 文字列のコピーが必要です
  • エラーの最大責任/感受性
  • コンプレックス




c++ templates qualifiers