禁止带有 `static_assert` 的函数

Forbids functions with `static_assert`

我想阻止调用某些函数。我们先忽略通过函数指针之类的调用函数的情况,只关注直接调用函数的情况。我可以用 = delete 做到这一点。但是,发出的诊断信息并不十分丰富。我考虑过使用 static_assert,您可以使用它来提供自定义诊断消息。我在函数体内放置了一个 static_assert(false, ...) 语句,希望它在函数被调用时触发。但是,事实证明,即使未调用该函数,static_assert 也会失败。有什么建议吗?

补充说明:该功能被无条件禁止。所以,std::enable_if 在这里不适用。这样一个函数的动机是我想防止某些使用,否则可以通过重载解析很好地编译。所以我不能只删除该功能。 deprecated 不是我想要的。我想要编译错误,而不是警告。

如果它是成员函数,那么 = delete 是您最好(最便携)的选择。否则,GCC 和 MSVC 都支持将函数标记为 "deprecated",这将导致编译器在调用函数时发出警告。

来自C++ mark as deprecated

#ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func
#endif

用法:

DEPRECATED(void badidea(int a, const char* b));

..... 现在使用 C++ 14,我们可以将其写为:

#define DEPRECATED(func, reason) [[deprecated(reason)]] func

使用情况:

DEPRECATED( void badidea(int a, const char* b), "This function was a bad idea");

我同意其他人的意见,您根本不应该为此使用 static_assert,而是将该函数标记为已弃用。

static_assert离子在编译时触发。对于一个普通的函数,这是它被解析的时间,而不是它被调用的时间。然而,对于template,它是实例化的时间。所以你可以让你的函数像这样 template

template <typename...>
struct always_false { static constexpr bool value = false; };

template <typename... Ts>
void
never_call_me(Ts&&...)
{
  static_assert(always_false<Ts...>::value,
                "You should have never called this function!");
}

如果 typename... 不适合您(因为函数过载),请尝试缩小范围以仅匹配您要出错的内容。

这里使用的技巧是 always_false<Ts...>::value 依赖于类型参数 Ts... 因此在实例化 template 之前无法对其求值。 (尽管我们可以清楚地看到它永远是 false。)