【问题标题】:C++ ternary operator with function calls带有函数调用的 C++ 三元运算符
【发布时间】:2014-01-19 12:23:11
【问题描述】:

我正在尝试使用三元运算符清理一些代码,但遇到了一些我无法理解的编译器错误。

我之前的代码看起来像这样并且运行良好。

if(!inFile.good())
     throw -2;
getline(inFile, inLine);

我正在尝试使用此代码来清理它。

(inFile.good()) ? getline(inFile, inLine) : throw -2;

但我收到以下错误。

g++ -w -o test orange_test.cpp
In file included from orange_test.cpp:4:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/iostream:39:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/streambuf:558:31: error: base class 'std::__1::ios_base' has private
  copy constructor
_LIBCPP_EXTERN_TEMPLATE(class basic_ios<char>)
                          ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/__config:462:54: note: expanded from macro '_LIBCPP_EXTERN_TEMPLATE'
#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
                                                 ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/ios:305:5: note: declared private here
ios_base(const ios_base&); // = delete;
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/istream:1706:31: note: implicit default copy constructor for
  'std::__1::basic_ios<char>' first required here
_LIBCPP_EXTERN_TEMPLATE(class basic_istream<char>)
                          ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/__config:462:54: note: expanded from macro '_LIBCPP_EXTERN_TEMPLATE'
#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
                                                 ^
./orange_model.hpp:145:23: note: implicit default copy constructor for 'std::__1::basic_istream<char>' first required here
                            (inFile.good()) ? getline(inFile, inLine) : throw -2;
                                              ^
1 error generated.
make: *** [main] Error 1

我无法理解它。三元运算符或范围是否存在一些我不知道的限制?任何帮助或见解将不胜感激。 提前致谢, 最大

编辑

从看来,主要错误似乎是

error: base class 'std::__1::ios_base' has private copy constructor

它在抱怨 std::getline(inFile, inLine) 函数。

回答

这段代码让它运行顺利。谢谢大家!

inFile.good() ? (void) getline(inFile, inLine) : throw -2;

【问题讨论】:

  • if 更改为条件运算符将被许多人(包括我)认为与清理相反。使用条件运算符的代码比使用原始if 的代码更加晦涩难懂。并且这条规则适用于条件运算符的几乎所有用途,它们不是选择这些两个值之一

标签: c++ std ternary-operator


【解决方案1】:

当一侧是throw 时,三元运算符有一个特殊规则。该规则的一部分是结果始终是临时右值,而不是引用。所以编译器需要对getline()返回值做一个拷贝,这会失败,因为流是不可拷贝的。

您可以显式丢弃 getline() 返回值以避免复制尝试:

inFile? (void)getline(inFile, inLine) : (throw -2);

但是,我不同意您的清理尝试。原件更容易理解和维护。

另外,你的意思是在getline() 之前还是之后测试inFile 的好坏?你可以这样做

getline(inFile, inLine) || (throw -2);

惯用的是其他一些语言,比如 perl 的 something or die "Error message"

【讨论】:

【解决方案2】:

如果您设置了三元条件(我个人不同意),您必须防止 throw() 部分导致复制(请参阅 Ben 的回答),您可以通过制作该部分来做到这一点使用逗号运算符评估引用,就像 getline 部分所做的那样:

inFile.good() ? getline(inFile, inLine) : (throw -2, inFile);

错误出现的地方是std::istream 的复制构造函数是私有的以防止复制,导致尝试复制失败。仅使用不带逗号运算符的 throw 就可以使用,例如,1 而不是 getline 调用。

getline返回你传入的istream &amp;inFile),最后一部分计算抛出,丢弃结果,计算并使用inFile作为其最终值。除了这里,一旦你执行了 throw,执行就不会继续评估 inFile,所以它不会对运行代码的逻辑产生影响。

【讨论】:

  • throw 表达式结果的具体类型是什么?
  • @Joker_vD,void。见this question
  • @Joker_vD:它是一个语句,它没有返回类型。这就像问while的类型。
  • 当一侧是throw 时,三元运算符有一个特殊规则。 throw 与任何类型兼容。但是,它确实会微妙地影响结果类型。所以逗号运算符可以解决这个问题。
  • inFile.good() ? (void)getline(inFile, inLine) : throw -2; 呢?
【解决方案3】:

您不应该使用投掷的“返回值”。

【讨论】:

    猜你喜欢
    • 2016-08-30
    • 2016-11-21
    • 1970-01-01
    • 2021-09-30
    • 2017-08-24
    • 2019-07-15
    • 2021-03-25
    • 1970-01-01
    相关资源
    最近更新 更多