用`static_assert`禁止函数

时间:2016-01-12 13:55:18

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

我想阻止调用某些函数。让我们忽略通过函数指针或其他东西调用函数的情况,只关注直接函数调用的情况。我可以使用= delete执行此操作。但是,所发布的诊断信息并不充分。我考虑使用static_assert,您可以使用{1}}提供自定义诊断消息。我在函数体中放置了一个static_assert(false, ...)语句,希望在调用函数时它会触发。但是,事实证明,即使未调用函数,static_assert也会失败。有什么建议吗?

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

2 个答案:

答案 0 :(得分:5)

我同意其他人的说法,你根本不应该使用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。)

答案 1 :(得分: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");