【问题标题】:Forbids functions with `static_assert`禁止使用 `static_assert` 的函数
【发布时间】:2016-04-17 04:21:11
【问题描述】:

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

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

【问题讨论】:

  • 使用= delete。这就是它的用途。
  • static_assert 不能真正阻止函数被调用,它的目的是编译时断言会产生错误。你可能想看看例如std::enable_if 代替。
  • 为什么函数存在,但它不应该被调用?只需将其从您的代码库中删除即可。
  • 我越重读你的问题,我就越困惑,你说的“防止某些函数被调用”是什么意思?您是否希望该功能根本不存在(这就是 using = delete 所做的,实际上删除它也是如此)?您想根据某些特定条件获得编译时错误吗?如果使用某些特定参数调用,或者仅从某些地方调用,您是否希望得到编译器错误?您想根据某些运行时条件阻止某人调用该函数吗?
  • @JoachimPileborg std::enable_if 不适用于此处。该功能被无条件禁止。如果我只是删除该函数,重载决议将选择另一个我不想要的函数。

标签: c++ c++11 compile-time static-assert deleted-functions


【解决方案1】:

我同意其他人的观点,您根本不应该为此使用 static_assert,而是将该功能标记为已弃用。

static_assertions 在编译时触发。对于一个普通函数来说,这是解析它的时间,而不是调用它的时间。然而,对于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&lt;Ts...&gt;::value 取决于类型参数Ts...,因此在实例化template 之前无法对其进行评估。 (尽管我们可以清楚地看到它始终是false。)

【讨论】:

  • always_false&lt;Ts...&gt;::value 和简单的 false 会有所作为吗?
  • 它确实有所作为!我想这将是我想要的解决方案。谢谢:)
  • 是的,诀窍是延迟条件的确定,直到类型参数已知。由于false 不依赖于参数,因此会立即对其进行评估。 always_false&lt;Ts...&gt;::value,虽然——好吧——总是错误的,技术上仍然依赖于Ts...
【解决方案2】:

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

来自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");

【讨论】:

  • 我没有。主要是因为我不知道它的存在,所以我可以忘记它!
  • 很高兴知道deprecated 的事情。但我真的需要编译错误,而不是警告。
  • 所以使用适当的编译器选项来使特定的警告成为错误(或者,像我一样,只需使用 -Werror 并使 all 警告成为错误)。
  • 完全同意= delete
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-05
  • 2021-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多