我正在为 C++17 实现我自己的 std::expected 类似物,并且我正在编写一个方法,该方法接受一个函数并在成功的预期值上调用它。如果预期包含错误,则不会发生任何事情。该方法将返回预期的本身。
这个想法是给定的函数不应该返回任何内容,例如记录。如果函数返回非空,我想生成编译时警告。我怎样才能做到这一点?
下面是该方法的代码
#define NOT_INVOCABLE_MESSAGE "function must be invocable on the given type"
template <class Success, class Error>
class Expected {
public:
template<typename F>
Expected<Success, Error>& on_success(F &&f) & noexcept {
static_assert(is_invocable_v<F, Success &>, NOT_INVOCABLE_MESSAGE);
// IDE highlight on the first comma: "Expected end of line in preprocessor expression"
// compiler error: "error: operator '&' has no right operand"
#if !is_same_v<void, invoke_result_t<F, Success &>>
#warning "return value of the given function will be ignored"
#endif
// warning gets generated even when condition is false
if constexpr (!is_same_v<void, invoke_result_t<F, Success &>>) {
#warning "return value of the given function will be ignored"
}
if (_hasValue) std::forward<F>(f)(_success);
return *this;
}
private:
union {
Success _success;
Error _error;
};
bool _hasValue;
}
我尝试使用
#warning
指令生成警告。我尝试了两种不同的条件:一种使用预处理器 #if
指令,另一种使用 if constexpr
。但第一个不允许条件体中出现逗号,第二个也不会阻止条件为 false 时生成 #warning
。还有其他方法吗?
#warning
是一个预处理器指令。预处理器在实际 C++ 编译之前运行。它没有 C++ 类型、表达式或语句的概念。它仅以 #if
和 #include
指令为条件,而这些指令又不了解 C++ 构造。它们仅支持文本包含、基于宏的标记替换和整数的简单算术。
没有 C++ 级别的函数告诉编译器发出警告,但仍然强制编译器编译程序。