Can a C++;函数是否声明为不能忽略返回值? 我试图确定C++函数是否可以以这样的方式声明:返回值不能被忽略(在编译时理想地检测到)。我试图用private(或者在C++11中,deleted)操作符void()声明一个类,以便在返回值未使用时捕获到对void的隐式转换
下面是一个示例程序:Can a C++;函数是否声明为不能忽略返回值? 我试图确定C++函数是否可以以这样的方式声明:返回值不能被忽略(在编译时理想地检测到)。我试图用private(或者在C++11中,deleted)操作符void()声明一个类,以便在返回值未使用时捕获到对void的隐式转换,c++,return-value,void,C++,Return Value,Void,下面是一个示例程序: class Unignorable { operator void(); }; Unignorable foo() { return Unignorable(); } int main() { foo(); return 0; } 不幸的是,我的编译器(clang-703.0.31)说: 并且不会在调用foo()时引发任何错误或警告。所以,这是行不通的。还有别的办法吗?特定于C++11或C++14或更高版本的答案就可以了。在C++17之
class Unignorable {
operator void();
};
Unignorable foo()
{
return Unignorable();
}
int main()
{
foo();
return 0;
}
不幸的是,我的编译器(clang-703.0.31)说:
并且不会在调用
foo()
时引发任何错误或警告。所以,这是行不通的。还有别的办法吗?特定于C++11或C++14或更高版本的答案就可以了。在C++17之前,我想到了这种方法:
#include <stdexcept>
#include <exception>
#include <boost/optional.hpp>
// proxy object which complains if it still owns the return
// value when destroyed
template<class T>
struct angry
{
angry(T t) : value_(std::move(t)) {}
angry(angry&&) = default;
angry(angry const&) = default;
angry& operator=(angry&&) = default;
angry& operator=(angry const&) = default;
~angry() noexcept(false)
{
if (value_) throw std::logic_error("not used");
}
T get() && {
T result = std::move(value_).value();
value_.reset();
return result;
}
boost::optional<T> value_;
};
// a function which generates an angry int
angry<int> foo()
{
return 10;
}
int main()
{
// obtain an int
auto a = foo().get();
// this will throw
foo();
}
看
然后强制将警告设置为错误:
clang++ -std=c++1z -Werror="unused-result"
从其他答案和评论中总结,基本上您有3种选择:
[[nodiscard]]
\uuuwur
(已定义
作为\uuuu属性\(((\uu警告\未使用的\结果\))
)或更便携的(仅限C++11及以上版本)[[gnu::警告\未使用的\结果]]
属性如果这三种方法都不可行,那么还有一种方法,那就是“负编译”。定义您的
不可识别的,如下所示:
struct Unignorable {
Unignorable () = default;
#ifdef NEGATIVE_COMPILE
Unignorable (const Unignorable&) = delete; // C++11
Unignorable& operator= (const Unignorable&) = delete;
//private: Unignorable (const Unignorable&); public: // C++03
//private: Unignorable& operator= (const Unignorable&); public: // C++03
/* similar thing for move-constructor if needed */
#endif
};
现在使用-DNEGATIVE_compile
或其他编译器(如MSVC)中的等效工具进行编译。无论结果在何处不被忽略,它都会给出错误:
但是,如果忽略结果,则不会给出任何错误:
使用任何现代的代码浏览器(如eclipse cdt),您都可以找到所有出现的foo()
,并修复那些没有给出错误的地方。在新编译中,只需删除“负编译”的预定义宏
这可能比简单地查找foo()
并检查其返回要好一些,因为可能有许多函数,例如foo()
,您可能不想忽略返回值
这有点乏味,但对于所有版本的C++都适用,所有的编译器都有。
< P>如果你使用MFC,你可以在函数声明之前尝试<强> CuffjReals>/Stuti>。
有关它的更多信息,请参见是否确定存在到void
的隐式转换?我在标准中找不到关于它的任何东西。(但我甚至不确定会转换什么。)好吧,当返回值没有“receiver”时,所有发生的事情都是构造和销毁一个临时对象。为此,C++17将有一个。wiki中的引用写入std::err,但您始终可以抛出一个异常。相关:。。。而且。。。这是一种很有趣的方法,我对它投了赞成票,但理想情况下,我正在寻找编译时解决方案。我不担心调用方破坏它的能力,因为他们总是可以通过将结果赋给某个对象,然后干脆不使用该值来破坏它。@GregHewgill那么我认为你在c++17之前运气不好,除非编译器在G++中扩展(可能也是clang++),我们还可以使用\uuuuwur
作为\uuuuuuuu属性((\uuuuu警告\u未使用的\uuuuuuuuu结果))的速记宏。
。此宏在::system(…)
函数之后使用。
int foo() __attribute__ ((warn_unused_result));
int foo(){return 123;}
int main()
{
foo(); //compiler warning
auto i = foo(); //valid
}
clang++ -std=c++1z -Werror="unused-result"
struct Unignorable {
Unignorable () = default;
#ifdef NEGATIVE_COMPILE
Unignorable (const Unignorable&) = delete; // C++11
Unignorable& operator= (const Unignorable&) = delete;
//private: Unignorable (const Unignorable&); public: // C++03
//private: Unignorable& operator= (const Unignorable&); public: // C++03
/* similar thing for move-constructor if needed */
#endif
};
auto x = foo(); // error
foo(); // no error