用户定义的文字为C++增加了哪些新功能?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (20)

例子:

// imaginary numbers
std::complex<long double> operator "" _i(long double d) // cooked form
{ 
    return std::complex<long double>(0, d); 
}
auto val = 3.14_i; // val = complex<long double>(0, 3.14)

// binary values
int operator "" _B(const char*); // raw form
int answer = 101010_B; // answer = 42

// std::string
std::string operator "" _s(const char* str, size_t /*length*/) 
{ 
    return std::string(str); 
}

auto hi = "hello"_s + " world"; // + works, "hello"_s is a string not a pointer

// units
assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

你觉得这个功能会证明自己吗?你还想要定义哪些其他文字,使得你的C ++代码更具可读性?

提问于
用户回答回答于

以下是使用用户定义文字而不是构造函数调用的优势:

#include <bitset>
#include <iostream>

template<char... Bits>
  struct checkbits
  {
    static const bool valid = false;
  };

template<char High, char... Bits>
  struct checkbits<High, Bits...>
  {
    static const bool valid = (High == '0' || High == '1')
                   && checkbits<Bits...>::valid;
  };

template<char High>
  struct checkbits<High>
  {
    static const bool valid = (High == '0' || High == '1');
  };

template<char... Bits>
  inline constexpr std::bitset<sizeof...(Bits)>
  operator"" _bits() noexcept
  {
    static_assert(checkbits<Bits...>::valid, "invalid digit in binary string");
    return std::bitset<sizeof...(Bits)>((char []){Bits..., '\0'});
  }

int
main()
{
  auto bits = 0101010101010101010101010101010101010101010101010101010101010101_bits;
  std::cout << bits << std::endl;
  std::cout << "size = " << bits.size() << std::endl;
  std::cout << "count = " << bits.count() << std::endl;
  std::cout << "value = " << bits.to_ullong() << std::endl;

  //  This triggers the static_assert at compile time.
  auto badbits = 2101010101010101010101010101010101010101010101010101010101010101_bits;

  //  This throws at run time.
  std::bitset<64> badbits2("2101010101010101010101010101010101010101010101010101010101010101_bits");
}

优点是运行时异常转换为编译时错误。无法将静态断言添加到采用字符串的位集ctor(至少不是没有字符串模板参数)。

用户回答回答于

我们真的需要它在C ++吗?

我在过去几年编写的代码中看到了一些用处,但仅仅因为我没有在C ++中使用它并不意味着它对另一个C ++开发人员来说并不有趣。

我们曾经用过C ++(我想是C语言),编译器定义的文字,把整数数字定义为短或长整数,将实数定义为float或double(或者甚至是long double),将字符串定义为普通或宽字符。

在C ++中,我们有可能创建我们自己的类型(即类),可能没有开销(内联等)。我们有可能将运算符添加到它们的类型中,让它们像类似的内置类型那样运行,这使得C ++开发人员能够像使用矩阵和复数一样自然地使用矩阵和复数,就像它们已经添加到语言本身一样。我们甚至可以添加演员操作员(这通常是一个坏主意,但有时候,这只是正确的解决方案)。

我们仍然错过了一个让用户类型表现为内置类型的方法:用户定义的文字。

所以,我认为这是语言的自然演变,但要尽可能完整:“ 如果您想创建一个类型,并且希望它的行为与内置类型一样可行,以下是这些工具。 ..

我猜想这与.NET将每个原始结构(包括布尔值,整数等)以及所有结构派生自Object的决定非常相似。这个决定让.NET远远超出了Java在处理原语时所能达到的范围,而不管Java将多少盒装/拆箱黑客加入到它的规范中。

你真的需要它在C ++吗?

这个问题是给回答的。不是Bjarne Stroustrup。不是草药萨特。不是任何C ++标准委员会的成员。这就是为什么你在C ++中有所选择,并且他们不会仅将有用的表示法限制为内置类型。

如果需要它,那么这是一个受欢迎的补充。如果不这样做,那么......不要使用它。它不会花你什么。

欢迎使用C ++,这是功能可选的语言。

臃肿??? 让我看看你的情结!

臃肿与复杂(双关意图)之间有区别。

能够编写复杂数字是“近期”添加到C和C ++中的两个特性之一:

// C89:
MyComplex z1 = { 1, 2 } ;

// C99: You'll note I is a macro, which can lead
// to very interesting situations...
double complex z1 = 1 + 2*I;

// C++:
std::complex<double> z1(1, 2) ;

// C++11: You'll note that "i" won't ever bother
// you elsewhere
std::complex<double> z1 = 1 + 2_i ;

现在,使用运算符重载,C99“double complex”类型和C ++“std :: complex”类型可以相乘,相加,相减等。

但在C99中,他们只是添加了另一种类型作为内置类型,并且内置了运算符重载支持。并且他们添加了另一个内置文字功能。

在C ++中,他们只是使用语言的现有特征,看到文字特征是语言的自然演变,因此添加了它。

在C语言中,如果你需要对另一种类型进行相同的符号增强,那么直到你将量子波函数(或3D点,或者你在工作领域中使用的任何基本类型)添加到C标准作为内置类型成功。

在C ++ 11中,你可以自己做:

Point p = 25_x + 13_y + 3_z ; // 3D point

它膨胀了吗?不,需求就在那里,正如C和C ++复合体如何需要一种表示其文字复数值的方式所显示的那样。

它设计错了吗?不,它的设计与所有其他C ++功能一样,考虑到可扩展性。

仅用于符号目的吗?不,因为它甚至可以为您的代码添加类型安全性。

例如,让我们设想一个面向CSS的代码:

css::Font::Size p0 = 12_pt ;       // Ok
css::Font::Size p1 = 50_percent ;  // Ok
css::Font::Size p2 = 15_px ;       // Ok
css::Font::Size p3 = 10_em ;       // Ok
css::Font::Size p4 = 15 ;         // ERROR : Won't compile !

然后很容易对值的赋值强制键入。

是危险的吗?

好问题。这些功能可以命名空间吗?如果是,那么累积奖金!

无论如何,像所有事情一样,如果工具使用不当,你可以自杀。C是强大的,如果你滥用C枪,你可以把你的头部掉下来。C ++拥有C枪,但也包括解剖刀,taser,以及您可以在工具包中找到的其他任何工具。你可以误用手术刀并自杀身亡。或者你可以构建非常优雅和健壮的代码。

所以,就像每个C ++特性一样,你真的需要它吗?这是你在C ++中使用它之前必须回答的问题。如果你不这样做,它不会花你什么。但如果你真的需要它,至少,这种语言不会让你失望。

日期示例?

在我看来,你的错误在于你在混合操作符:

1974/01/06AD
    ^  ^  ^

这是无法避免的,因为作为操作员,编译器必须解释它。而且,AFAIK,这是一件好事。

为了找到解决问题的方法,我会以其他方式编写文字。例如:

"1974-01-06"_AD ;   // ISO-like notation
"06/01/1974"_AD ;   // french-date-like notation
"jan 06 1974"_AD ;  // US-date-like notation
19740106_AD ;       // integer-date-like notation

就个人而言,我会选择整数和ISO日期,但这取决于你的需求。这是让用户定义自己的文字名称的关键。

扫码关注云+社区