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不,它不能。我的意思是让用户决定是否需要验证。所以用户不需要为他不需要的东西付费。但仔细想想,目前公认的答案可能是更好的选择:)