首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >C++:带三元线if语句的cout

C++:带三元线if语句的cout
EN

Stack Overflow用户
提问于 2011-04-20 14:38:20
回答 7查看 14.1K关注 0票数 10

我得到这个错误:“错误:没有上下文类型信息的重载函数”。

代码语言:javascript
代码运行次数:0
运行
复制
cout << (i % 5 == 0) ? endl : "";

我正在做的事情是可能的吗?是我做错了,还是我必须重载<<操作符?

EN

回答 7

Stack Overflow用户

发布于 2011-04-20 14:50:13

它不会以这种方式工作(即使您修复了优先级错误)。这里有两个问题,第二个比第一个更严重。

第一个问题是std::endl是一个模板。它是一个函数模板。模板必须是专门化的。为了专门化该模板,编译器必须知道(推断)模板参数。当你这样做的时候

代码语言:javascript
代码运行次数:0
运行
复制
std::cout << std::endl;

编译器使用operator <<期望的特定函数指针类型来确定如何专门化std::endl模板。

然而,在您的示例中,您实际上是通过将std::endl移动到operator <<子表达式中来将std::endl?:“分离”的。现在编译器必须首先编译这个表达式

代码语言:javascript
代码运行次数:0
运行
复制
(i % 5 == 0) ? endl : ""

无法编译此表达式,因为编译器不知道如何专门化std::endl模板。在没有任何上下文的情况下,无法推断模板参数。

例如,这个简单的C++程序

代码语言:javascript
代码运行次数:0
运行
复制
#include <iostream>
int main() {
   std::endl;
}

也会因为同样的原因而无法编译:没有上下文,编译器就不知道如何实例化std::endl

您可以通过显式指定模板参数来“帮助”编译器解决该问题

代码语言:javascript
代码运行次数:0
运行
复制
(i % 5 == 0) ? endl<char, char_traits<char> > : "";

这将显式地告诉编译器如何实例化endl。您收到的原始错误消息将会消失。

然而,这将立即揭示该表达式的第二个更严重的问题: specialized endl是一个函数(在此上下文中,它衰减为函数指针),而""是一个字符串文字。你不能像那样在?:操作符中混合使用函数指针和字符串。这些类型不兼容。它们不能一起用作三进制?:的第二个和第三个操作数。编译器将对第二个问题发出不同的错误消息。

因此,基本上,您在这里遇到最新问题就好像您试图做一些类似于

代码语言:javascript
代码运行次数:0
运行
复制
cout << (i % 5 == 0 ? 10 : "Hi!");

这将不会进行编译,原因与您的表达式不会进行编译的原因相同。

因此,您尝试编写的表达式不能以这种方式编写。在不尝试使用?:操作符的情况下重写它。

作为支持,请参阅以下文字记录:

代码语言:javascript
代码运行次数:0
运行
复制
$ cat qq.cpp
#include <iostream>
using namespace std;
int main (void) {
    int i = 5;
    cout << ((i % 5 == 0) ? endl : "");
    return 0;
}

$ g++ -o qq qq.cpp
qq.cpp: In function 'int main()':
qq.cpp:5: error: overloaded function with no contextual type information
票数 34
EN

Stack Overflow用户

发布于 2011-04-20 14:47:24

?运算符的两个参数必须是相同类型的(至少在潜在的提升、隐式构造函数、强制转换运算符等加入之后)。std::endl实际上是一个函数模板(详细信息如下),然后流调用它来影响其状态:它不像""那样是字符串文字。

所以,你不能准确地做到这一点,但你可能可以得到你真正想要的行为-考虑是否...

代码语言:javascript
代码运行次数:0
运行
复制
expr ? "\n" : ""

...meets你的需要-它是类似的,但不会刷新流(我的意思是,std::cout通常应该尽可能不频繁地刷新-特别是通过低级库代码-因为这样可以提供更好的性能)。(它也更灵活,例如expr ? "whatever\n" : "" /不能将endl附加到字符串文字。)

例如,对于GCC 4.5.2,endl为:

代码语言:javascript
代码运行次数:0
运行
复制
template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>& 
    endl(basic_ostream<_CharT, _Traits>& __os)
    { return flush(__os.put(__os.widen('\n'))); }
票数 15
EN

Stack Overflow用户

发布于 2011-04-20 14:47:34

如果other.

  • endl是一个模板,而上下文没有提供足够的信息可供选择,则
  • ?:的两个备选方案必须具有相同的类型,或者其中一个可以转换为模板。所以它甚至没有类型。(这是您的错误消息)。
  • 正如其他人已经说过的,绑定不是您期望的绑定。
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5726427

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档