13

cppreferenceには、テンプレート化されたユーザーリテラル演算子を使用できるという言及がありますが、いくつかの制限があります

charリテラル演算子がテンプレートの場合、空のパラメーター リストが必要であり、テンプレート パラメーターを 1 つだけ持つことができます。これは、次のような要素 type を持つ非型テンプレート パラメーター パックでなければなりません。

template <char...> double operator "" _x();

だから私は以下のコードのようなものを書きました:

template <char...> 
double operator "" _x()
{
    return .42;
}

int main()
{
    10_x; // empty template list, how to specify non-empty template parameters?
}

質問:

  1. コードは機能しますが、空でないテンプレート パラメーターで演算子を使用するにはどうすればよいですか? 10_x<'a'>;または10_<'a'>x;コンパイルされません。
  2. そのようなテンプレート化された演算子の実際の使用例はありますか?
4

3 に答える 3

10
10_x; // empty template list, how to specify non-empty template parameters?

それは正しくありません。テンプレート パラメータ リストが空ではありません。あなたが書くとき:

template <char... Cs> 
??? operator "" _x()

リテラルのCs左側のものから入力されます。つまり、次のように記述します。

10_x

それは呼び出します:

operator ""_x<'1', '0'>();

簡単な例の 1 つは、次のようなコンパイル時のオーバーフロー セーフなバイナリ リテラルを作成することです。

template <uint64_t V>
constexpr uint64_t make_binary() {
    return V;
}

template <uint64_t V, char C, char... Cs>
constexpr uint64_t make_binary() {
    static_assert(C == '0' || C == '1', "invalid binary");

    return make_binary<2*V + C - '0', Cs...>();
}

template <char... Cs> 
uint64_t operator "" _b()
{
    static_assert(sizeof...(Cs) <= 64, "overflow");

    return make_binary<0, Cs...>();
}

uint64_t a = 101_b; // OK: a == 5
uint64_t b = 102_b; // error: invalid
uint64_t c = 11111111110000000000111111111100000000001111111111000000000011111111110000000000_b; // error: overflow
于 2016-09-30T16:30:32.900 に答える
7

テンプレート パラメータは既に指定されています。これらは、リテラル値を構成するソース コード文字です。したがって、10_x実際に呼び出しているのは次のとおりです。

template<> double operator "" _x<'1', '0'>();

これが実際の例です。エラーなしでコンパイルされ、アサーションはトリガーされません。

#include <cassert>

enum class MyEnum
{
  ONE,
  TWO,
  THREE
};

template<char...> MyEnum operator "" _e();

template<> MyEnum operator "" _e<'1'>()
{
  return MyEnum::ONE;
}
template<> MyEnum operator "" _e<'2'>()
{
  return MyEnum::TWO;
}
template<> MyEnum operator "" _e<'3'>()
{
  return MyEnum::THREE;
}

int main()
{
  assert(1_e == MyEnum::ONE);
  assert(2_e == MyEnum::TWO);
  assert(3_e == MyEnum::THREE);
}
于 2016-09-30T16:32:37.350 に答える
2

必要に応じて、パラメーターパックを何らかの形で作成するか(他の人が述べたように)、コンパイル時の文字列としてアクセスできます。

template<int N>
constexpr double f(const char(&str)[N]) { return .42; }

template <char... C> 
constexpr double operator "" _x()
{
     return f({C...});
}

そのようなテンプレート化された演算子の実際の使用例はありますか?

上記の手法を使用して、コンパイル時の文字列から数値への10_xコンバーターを処理し、代わりに何かのようなものを使用できますf("10")

于 2016-09-30T16:42:42.337 に答える