带字符串文字的前缀vs中缀运算符*

时间:2015-12-17 21:38:16

标签: c++ string c++11 operators

我最近向answer提供了关于如何获得类似Python的字符串重复的this question,例如"hello" * 2提供"hellohello"

我不会在这里重复定义,但函数声明是:

std::string repeat(std::string str, const std::size_t n);

当然可以像:

一样使用
std::cout << repeat("helloworld", 2) << std::endl;

为了更接近Python版本,我认为我重载operator*。理想情况下,我使用通用引用来避免额外的std::string移动,但operators must use a user-defined type。所以我尝试了这个:

#include <type_traits> // std::enable_if_t, std::is_integral
#include <utility>     // std::move

template <typename T, typename = std::enable_if_t<std::is_integral<T>::value>>
std::string operator*(std::string str, const T n)
{
    return repeat(std::move(str), static_cast<std::size_t>(n));
}

现在我可以这样做:

std::cout << (std::string("helloworld") * 2) << std::end;

和此:

std::cout << operator*("helloworld", 2) << std::endl;

但不是这样:

std::cout << ("helloworld" * 2) << std::endl;
// error: invalid operands to binary expression ('const char *' and 'int')

为什么不呢?

2 个答案:

答案 0 :(得分:5)

定义重载运算符时,至少有一个操作数必须是用户定义的类型。对于预定义类型,所有运算符都是预定义的,否则是禁止的。

如果您明确转换为std::string string ctor,其char const *作为参数可以/将用于将文字转换为std::string但是,如果没有这个,编译器就无法进行转换。

同样,当您以operator*("helloworld", 2)更明确地调用运算符时,编译器&#34;知道&#34;它需要将字符串文字转换为operator *重载支持的类型,因此它(基本上)枚举字符串文字可以转换的所有类型,然后查看它是否可以找到{{1} 1}}适合其中一种类型。如果它找到多个,它会(如果内存服务)对候选operator *实现进行正常的重载决策以决定使用哪个。

然而,仅使用表达式operator *,两种类型都是内置的,因此它只检查内置运算符。由于它们都不适合,因此禁止表达。

请注意,使用当前编译器,您可以在字符串文字上使用string-literal * int的后缀来创建s

std::string

答案 1 :(得分:3)

由于"helloworld"不是std::string,因此它是char数组。