【问题标题】:operator++ as both a postfix and prefix doesn't work with clangoperator++ 作为后缀和前缀都不适用于 clang
【发布时间】:2012-12-31 10:11:35
【问题描述】:

我试图写一个既可以用作前缀又可以用作后缀运算符的运算符

#include <iostream>
#include <utility>

struct B { 
  // ...
};

template<typename ...T>
void operator++(B, T...) {
  std::cout << ((sizeof...(T) == 0) ? "prefix" : "postfix") << std::endl;
}

int main() {
  B b;
  b++;
  ++b;
}

GCC 可以编译并正常工作,但是 clang 说

main.cpp:9:24: 错误:重载后自增运算符的参数必须为“int”类型(不是“T...”)

void operator++(B, T...) {

谁是对的?


感谢任何帮助我了解 GCC 行为的人。我提交了一份新的 Clang 错误报告:

http://llvm.org/bugs/show_bug.cgi?id=14995

【问题讨论】:

  • 我不确定这是否可行 - 措辞是“具有两个参数的非成员函数(第二个应为 int 类型)......”
  • 这是 clang 存在的理由。如果您编写 stoopid 代码,则 clang 保留通过明确的错误消息告诉您的权利。好的错误信息胜过粗制滥造的语言标准,这种观点还没有得到足够的应用。令人钦佩的错误,也许,我确实喜欢他们正在尝试做的事情。不要把贵宾犬放在微波炉里。
  • 但关键是可以为函数生成有效的特化(不需要参数包始终为空(这是非法的))。
  • @Hans 称 C++ 语言标准为“粗制滥造”缺乏远见。很少有(少于五个?我能说出一个)具有更严格的语言和定义的语言标准。
  • @KonradRudolph 出于好奇,你能想到的那个是什么?

标签: c++ templates c++11 operators language-lawyer


【解决方案1】:

原始答案:未删除,因为它可能包含有用信息

我想说这一切都归结为重载运算符 template 是否被认为是重载运算符。从逻辑上讲,我想事实并非如此,Clang 是错误的:我认为模板应该首先被选为基于名称和签名兼容性的重载解析的候选者,然后实例化,然后(可能)选择。在我看来,只有在实例化之后,编译器才应该检查生成的 function 是否具有适当数量的参数。

但这只是我的意见。根据 § 13.5.7/1 关于后缀 operator ++ 的重载:

"如果函数是具有一个参数的成员函数(应为 int 类型)或具有两个参数的非成员函数(第二个应为类型int),它为该类型的对象定义了后缀递增运算符 ++"

该标准似乎没有阐明函数 template 是否应被视为 函数 涉及合法运算符重载签名的限制(至少,我找不到任何可以解决这种歧义的句子)。只要这是真的,这个问题就很难给出一个明确的答案,我们只剩下意见了。

但我想提一下这个问题的另一个相关方面:一致性

虽然问题文本中的代码确实不能在 Clang 上编译,但以下代码可以:

template<typename... Ts>
int operator + (X x1, Ts... args)
{
    return 0;
}

我看不出这两种情况在概念上有什么区别:如果要在实例化之前检查运算符重载的签名,那么上面的定义也不应该编译。如果不是这种情况,那么问题文本中的代码应该可以编译。

所以在我看来,要么 GCC 是对的,要么它们都是错的。

更新:

正如@JesseGood 和@SethCarnegie 正确指出的那样,根据 14.7/4:

“特化是一个类、函数或类成员,它要么被实例化,要么被显式特化。”

此外,根据 14.6/8:

“对于可以生成有效专业化的模板,不应发出诊断。”

因此,看来Clang确实是错误的,不会产生编译错误对于问题文本中的算子函数模板。

【讨论】:

  • 您显示的函数模板是“格式错误,不需要诊断”,因为模板的所有实例都需要一个空参数包。这在第 14 条的某处指定。
  • @JohannesSchaub-litb:我明白了。如果我无法修补它,我会再考虑一下并删除我的答案
  • The Standard does not seem to clarify whether a function template shall be considered as a function 我认为确实如此。 13.5p1怎么样:A specialization of an operator function template is also an operator function.
  • 我以为我们做到了,实例化是从 14.7p4 开始的专业化:A specialization is a class, function, or class member that is either instantiated or explicitly specialized。我还以为Seth Carnegie's comment was spot on
  • 嗯,在 14.6p8 中提到:No diagnostic shall be issued for a template for which a valid specialization can be generated.
猜你喜欢
  • 2017-10-18
  • 1970-01-01
  • 2016-06-17
  • 2011-04-20
  • 1970-01-01
  • 2019-04-19
  • 1970-01-01
  • 2020-11-26
相关资源
最近更新 更多