C++: cout加上一个三百年的if语句

时间:2022-11-11 18:31:38

I get this ERROR: "error: overloaded function with no contextual type information".

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

cout << (i % 5 == 0) ? endl : "";

Is what I am doing possible; am I just doing it wrong, or do I have to overload the << operator?

我所做的是可能的;我只是做错了,还是必须重载< <运算符?< p>

7 个解决方案

#1


30  

It worn't work that way (even if you fix the the precedence error). You have two problems here, the second more severe than the first.

它不能那样工作(即使你修正了优先错误)。这里有两个问题,第二个比第一个严重。

The first problem is that std::endl is a template. It is a function template. A template has to be specialized. In order to specialize that template the compiler has to know (to deduce) the template arguments. When you do

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

std::cout << std::endl;

the specific function pointer type expected by operator << is what the compiler uses to figure out how to specialize the std::endl template.

操作符<< <所期望的特定函数指针类型是编译器用来确定如何专门化std::endl模板的。< p>

However in your example you essentially "detached" the std::endl from operator << by moving the std::endl into an ?: subexpression. Now the compiler has to compile this expression first

然而,在您的示例中,您实际上是通过将std::endl移动到?:子表达式,将std::endl从操作符< <中分离出来。现在编译器必须先编译这个表达式< p>

(i % 5 == 0) ? endl : ""

This expression cannot be compiled since the compiler does not know how to specialize the std::endl template. There's no way to deduce the template arguments without any context.

由于编译器不知道如何专门化std:::endl模板,所以无法编译此表达式。没有上下文可以推断模板参数。

For example, this simple C++ program

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

#include <iostream>
int main() {
   std::endl;
}

will also fail to compile for the very same reason: without context the compiler does not know how to instantiate std::endl.

由于同样的原因,编译失败:没有上下文,编译器不知道如何实例化std::endl。

You can "help" the compiler to resolve the problem by specifying the template arguments explicitly

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

(i % 5 == 0) ? endl<char, char_traits<char> > : "";

This will explicitly tell compiler how to instantiate endl. The original error message you were getting will go away.

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

However, this will immediately reveal the second, more serious problem with that expression: specialized endl is a function (which decays to a function pointer in this context) while "" is a string literal. You cannot mix a function pointer and a string literal in a ?: operator like that. These types are incompatible. They cannot be used together as the 2nd and the 3rd operand of ternary ?:. The compiler will issue a different error message about this second problem.

然而,这将立即揭示该表达式的第二个更严重的问题:专门化的endl是一个函数(在此上下文中它衰减为一个函数指针),而“”是一个字符串文字。在这样的操作符中,不能将函数指针和字符串文字混合在一起。这些类型是不相容的。它们不能同时作为三元的第二和第三个操作数。对于第二个问题,编译器将发出不同的错误消息。

So, basically, that latest problem you have here is as if you tried to do something like

所以,基本上,你现在遇到的最新的问题就好像你试图做一些类似的事情

cout << (i % 5 == 0 ? 10 : "Hi!");

This will not compile for the very same reason your expression will not compile.

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

So, the expression you are trying to write cannot be written that way. Rewrite it without trying to use the ?: operator.

所以,你要写的表达式不能这样写。重写它,不要尝试使用?:操作符。


As support, see the following transcript:

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

$ 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

#2


15  

The two arguments to the ? operator must be of the same type (at least after potential promotions, implicit constructors, casting operators etc. kick in). std::endl is actually a function template (details below) which the stream then invokes to affect its state: it is not a string literal like "".

这两个论点?操作符必须是相同的类型(至少在潜在的升级、隐式构造符、浇注操作符等加入之后)。endl实际上是一个函数模板(详细内容如下),然后流调用该模板来影响其状态:它不是一个字符串字面量“”。

So, you can't do this exactly, but you can probably get the behaviour you actually want - consider whether...

所以,你不能这么做,但是你可能会得到你想要的行为——考虑一下……

expr ? "\n" : ""

...meets your needs - it is similar but doesn't flush the stream (IMHO, std::cout should generally be flushed as infrequently as possible - especially by low level library code - as that provides better performance). (It's also more flexible, e.g. expr ? "whatever\n" : "" / can't append endl to a string literal.)

…满足您的需求——它是相似的,但是并不刷新流(IMHO, std::cout通常应该尽可能不频繁地刷新——特别是通过低级库代码——因为这样可以提供更好的性能)。(它也更灵活,例如:expr ?“whatever\n”:“/不能将endl附加到字符串文字。)

E.g. for GCC 4.5.2, endl is:

对于GCC 4.5.2, endl为:

template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>& 
    endl(basic_ostream<_CharT, _Traits>& __os)
    { return flush(__os.put(__os.widen('\n'))); }

#3


3  

  • The two alternatives of ?: must have the same type or one be convertible to the other.

    ?的两个选项必须具有相同的类型,或者一个可转换为另一个。

  • endl is a template and the context doesn't give enough information for which to choose. So it hasn't even a type. (Thats is your error message).

    endl是一个模板,上下文没有提供足够的信息供选择。所以它甚至没有类型。这是你的错误信息。

  • As other already said, the binding isn't the one you expect.

    正如其他已经说过的,绑定不是您所期望的。

#4


2  

It may well be possible (I doubt it myself). However, it's also silly, effectively as silly as:

这很可能(我自己也怀疑)。然而,它也很愚蠢,实际上就像:

cout << "";

What you should be doing in this case is a simple:

在这种情况下,你应该做的是简单的:

if (i % 5 == 0) cout << endl;

You shouldn't use ternary just for the sake of using it. Actually you shouldn't use any language feature just for the sake of using it. I don't write code like:

你不应该为了使用三进制而使用三进制。实际上,您不应该仅仅为了使用它而使用任何语言特性。我不会这样写代码:

if (1) { doSomething(); }

just because I can. A simple doSomething(); is much better.

只是因为我可以。一个简单的doSomething();要好得多。

#5


0  

Try this, it works:

试试这个,它的工作原理:

cout << ((i % 5 == 0) ? "\n" : "");

#6


0  

This is how it is supposed to look like to make it work correctly:

这就是让它正确工作的样子:

cout << ((i % 5 == 0) ? '\n' : " ");

#7


-1  

Operator << has higher priority than ?:. Try this:

操作符< <具有比?:更高的优先级。试试这个:< p>

cout << ((i % 5 == 0) ? endl : "");

#1


30  

It worn't work that way (even if you fix the the precedence error). You have two problems here, the second more severe than the first.

它不能那样工作(即使你修正了优先错误)。这里有两个问题,第二个比第一个严重。

The first problem is that std::endl is a template. It is a function template. A template has to be specialized. In order to specialize that template the compiler has to know (to deduce) the template arguments. When you do

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

std::cout << std::endl;

the specific function pointer type expected by operator << is what the compiler uses to figure out how to specialize the std::endl template.

操作符<< <所期望的特定函数指针类型是编译器用来确定如何专门化std::endl模板的。< p>

However in your example you essentially "detached" the std::endl from operator << by moving the std::endl into an ?: subexpression. Now the compiler has to compile this expression first

然而,在您的示例中,您实际上是通过将std::endl移动到?:子表达式,将std::endl从操作符< <中分离出来。现在编译器必须先编译这个表达式< p>

(i % 5 == 0) ? endl : ""

This expression cannot be compiled since the compiler does not know how to specialize the std::endl template. There's no way to deduce the template arguments without any context.

由于编译器不知道如何专门化std:::endl模板,所以无法编译此表达式。没有上下文可以推断模板参数。

For example, this simple C++ program

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

#include <iostream>
int main() {
   std::endl;
}

will also fail to compile for the very same reason: without context the compiler does not know how to instantiate std::endl.

由于同样的原因,编译失败:没有上下文,编译器不知道如何实例化std::endl。

You can "help" the compiler to resolve the problem by specifying the template arguments explicitly

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

(i % 5 == 0) ? endl<char, char_traits<char> > : "";

This will explicitly tell compiler how to instantiate endl. The original error message you were getting will go away.

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

However, this will immediately reveal the second, more serious problem with that expression: specialized endl is a function (which decays to a function pointer in this context) while "" is a string literal. You cannot mix a function pointer and a string literal in a ?: operator like that. These types are incompatible. They cannot be used together as the 2nd and the 3rd operand of ternary ?:. The compiler will issue a different error message about this second problem.

然而,这将立即揭示该表达式的第二个更严重的问题:专门化的endl是一个函数(在此上下文中它衰减为一个函数指针),而“”是一个字符串文字。在这样的操作符中,不能将函数指针和字符串文字混合在一起。这些类型是不相容的。它们不能同时作为三元的第二和第三个操作数。对于第二个问题,编译器将发出不同的错误消息。

So, basically, that latest problem you have here is as if you tried to do something like

所以,基本上,你现在遇到的最新的问题就好像你试图做一些类似的事情

cout << (i % 5 == 0 ? 10 : "Hi!");

This will not compile for the very same reason your expression will not compile.

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

So, the expression you are trying to write cannot be written that way. Rewrite it without trying to use the ?: operator.

所以,你要写的表达式不能这样写。重写它,不要尝试使用?:操作符。


As support, see the following transcript:

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

$ 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

#2


15  

The two arguments to the ? operator must be of the same type (at least after potential promotions, implicit constructors, casting operators etc. kick in). std::endl is actually a function template (details below) which the stream then invokes to affect its state: it is not a string literal like "".

这两个论点?操作符必须是相同的类型(至少在潜在的升级、隐式构造符、浇注操作符等加入之后)。endl实际上是一个函数模板(详细内容如下),然后流调用该模板来影响其状态:它不是一个字符串字面量“”。

So, you can't do this exactly, but you can probably get the behaviour you actually want - consider whether...

所以,你不能这么做,但是你可能会得到你想要的行为——考虑一下……

expr ? "\n" : ""

...meets your needs - it is similar but doesn't flush the stream (IMHO, std::cout should generally be flushed as infrequently as possible - especially by low level library code - as that provides better performance). (It's also more flexible, e.g. expr ? "whatever\n" : "" / can't append endl to a string literal.)

…满足您的需求——它是相似的,但是并不刷新流(IMHO, std::cout通常应该尽可能不频繁地刷新——特别是通过低级库代码——因为这样可以提供更好的性能)。(它也更灵活,例如:expr ?“whatever\n”:“/不能将endl附加到字符串文字。)

E.g. for GCC 4.5.2, endl is:

对于GCC 4.5.2, endl为:

template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>& 
    endl(basic_ostream<_CharT, _Traits>& __os)
    { return flush(__os.put(__os.widen('\n'))); }

#3


3  

  • The two alternatives of ?: must have the same type or one be convertible to the other.

    ?的两个选项必须具有相同的类型,或者一个可转换为另一个。

  • endl is a template and the context doesn't give enough information for which to choose. So it hasn't even a type. (Thats is your error message).

    endl是一个模板,上下文没有提供足够的信息供选择。所以它甚至没有类型。这是你的错误信息。

  • As other already said, the binding isn't the one you expect.

    正如其他已经说过的,绑定不是您所期望的。

#4


2  

It may well be possible (I doubt it myself). However, it's also silly, effectively as silly as:

这很可能(我自己也怀疑)。然而,它也很愚蠢,实际上就像:

cout << "";

What you should be doing in this case is a simple:

在这种情况下,你应该做的是简单的:

if (i % 5 == 0) cout << endl;

You shouldn't use ternary just for the sake of using it. Actually you shouldn't use any language feature just for the sake of using it. I don't write code like:

你不应该为了使用三进制而使用三进制。实际上,您不应该仅仅为了使用它而使用任何语言特性。我不会这样写代码:

if (1) { doSomething(); }

just because I can. A simple doSomething(); is much better.

只是因为我可以。一个简单的doSomething();要好得多。

#5


0  

Try this, it works:

试试这个,它的工作原理:

cout << ((i % 5 == 0) ? "\n" : "");

#6


0  

This is how it is supposed to look like to make it work correctly:

这就是让它正确工作的样子:

cout << ((i % 5 == 0) ? '\n' : " ");

#7


-1  

Operator << has higher priority than ?:. Try this:

操作符< <具有比?:更高的优先级。试试这个:< p>

cout << ((i % 5 == 0) ? endl : "");