C++ c++;在编译时检查是否调用了函数

C++ c++;在编译时检查是否调用了函数,c++,c++14,compile-time,C++,C++14,Compile Time,可能的重复我将在底部解释 我想知道是否可以进行编译时检查,以查看是否在调用另一个函数之前先调用一个函数。 我的用例如下所示: auto f = foo(); if(!f.isOk()) return f.getError(); auto v = f.value(); 所以在这种情况下,如果用户在调用value之前没有调用isOk,我希望得到一个编译时错误。 据我所知,搜索它似乎不可能,但我想问一下,以确保我没有错过任何C++魔术。 FauxDupes: 这是关于知道你的函数是否是c

可能的重复我将在底部解释

我想知道是否可以进行编译时检查,以查看是否在调用另一个函数之前先调用一个函数。
我的用例如下所示:

auto f = foo();
if(!f.isOk())
    return f.getError();

auto v = f.value();
所以在这种情况下,如果用户在调用value之前没有调用isOk,我希望得到一个编译时错误。 据我所知,搜索它似乎不可能,但我想问一下,以确保我没有错过任何C++魔术。 FauxDupes:


这是关于知道你的函数是否是constexpr函数。我想知道一个函数是否在另一个函数被调用之前就被调用了。

如果不大幅改变您的设计,您想要的是不可能直接实现的

您可以通过将它们包装在一个调用中来强制始终同时调用:

??? foo(const F& f) {
     return f.isOk() ? f.value() : f.getError();
}
然而,这只是将问题转移到选择返回类型上。您可以返回一个
std::variant
,或者在设计上做一些更改后返回一个
std::optional
,但是无论您做什么,都将留给调用方检查实际返回的内容

不要假设最愚蠢的用户,也不要试图保护他们免受任何可能的错误。相反,假设他们确实阅读了文档

必须检查返回值是否有效是一种非常常见的模式:返回指针的函数可以返回空指针,返回迭代器的函数可以返回
end
迭代器。这种情况有很好的文档记录,负责的调用方将检查返回值是否有效

为了获得更多的灵感,我建议你,C++的一个相当现代的添加,它也很大程度上依赖于用户知道他们正在处理什么。 PS:正如一个反例,用户可能会编写如下代码,这使得在编译时无法使用当前设计进行所需的检查:

 int n;
 std::cin >> n;
 auto f = foo();
 if(n > 10 && !f.isOk())
    return f.getError();

 auto v = f.value();

这种事情的一种策略是利用
\uuuu属性(warn\u unused\u result))
(对于GCC)或(msvc)

然后,更改
foo()
以返回错误条件:

SomeObj obj;
auto result = foo(obj);

这将促使调用者处理错误。当然有明显的限制:
foo()
不能是构造函数,例如,调用者不能对类型名使用
auto

确保顺序的一种方法是将临时依赖项转换为物理依赖项:

将方法
F::getError()
F::value()
移动到它们自己的结构包装器中(
Error
value

bool F::isOk()
更改为类似以下内容:

  • std::variant F::isOk()
然后,在调用
isOk
之前,不能使用
Error::getError
Value::Value()

auto f = foo();
auto isOk = f.isOk();
if (auto* e = std::get_if<Error>(&isOk)) // Or std::visit
    return e->getError();
auto& value = std::get<Value>(&isOk);
auto v = value.value();
auto f=foo();
自动isOk=f.isOk();
if(auto*e=std::get_if(&isOk))//或std::visit
返回e->getError();
auto&value=std::get(&isOk);
自动v=值。值();

通常,答案是“否”。对于源文件的单独编译,编译器本身不一定知道是否调用了一个函数,更不用说是否在另一个函数之后调用了它。实际上,如果您有两个函数,并且要求一个总是在另一个之前被调用,那么将这两个函数组合成一个,这样组合的函数就可以确保以正确的顺序执行必要的操作,而不管什么代码调用它或调用它多少次。在您的情况下,我将取消
isOk()
函数,然后
foo()
如果一切都不正常,则抛出异常。如果要进行编译时检查,则必须使用模板。如果函数是constexpr,那么就很容易了。它可以通过一些模板特殊结构来实现,但是如果它真的值得或者最好重新考虑设计,我会想到什么。如果严格来说没有必要在
value
之前调用
isOk
,您也可以像标准库通常所做的那样,制定一些必须满足的先决条件,使
value
成功(编写一份好的文档)。然后由用户在调用
value
(例如,通过调用
isOk
)@churill之前确保这些先决条件适用,但是这些先决条件可以在编译时检查吗?这看起来像是运行时的事情。@turoni不,它不能。我的意思是让用户决定是否需要验证。所以用户不需要为他不需要的东西付费。但仔细想想,目前公认的答案可能是更好的选择:)