13

cppreference上提到可以有模板化的用户文字操作符,但有一些限制:

如果字面量运算符是一个模板,它必须有一个空的参数列表,并且只能有一个模板参数,它必须是一个元素类型的非类型模板参数包char,例如

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'>();

一个简单的例子是构建一个编译时,溢出安全的二进制文字,这样:

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 回答