我试图在编译时确定是否曾调用过某个函数。具体来说,如果是:
,我想抛出一个静态断言失败template <typename T>
auto Function(T value) -> std::enable_if<someCondition, int>
{
// this is the function I want to call
}
template <typename... T>
int Function(T...)
{
// This function should never be called, instead I want
// a compile-time failure if this is called, because it
// means the above function wasn't successfully resolved.
}
我想这样做的原因是因为无法正确调用Function()
并使用正确的条件会导致数千行编译器错误消息,这些消息对于那些不熟悉这些消息的人来说都不是很有用。代码库。
我不想在static_assert
中放置Function
的原因是因为我们拥有许多这些功能,而我们有办法通过宏生成Catch-all
版本,这将避免不必要的代码库增长,同时产生更多有用的错误消息。
可以这样做吗?
答案 0 :(得分:19)
根据您对问题的评论,您不希望在此处static_assert
:
template <typename T>
auto Function(T value) -> std::enable_if<someCondition, int>
{
// this is the function I want to call
}
...但实际上static_assert
并没有错:
template <typename... T>
struct dependent_false { static constexpr bool value = false; };
template <typename... T>
int Function(T...)
{
static_assert(dependent_false<T...>::value, "you are passing the wrong arguments!");
}
正如您所正确指出的那样,简单的static_assert(false, "...");
会在模板定义时失败。要获得仅在实例化时失败的东西,你需要一个依赖表达式,dependent_false
辅助结构是一种简单的方法来获得与类型相关的东西,几乎总是false
,但编译器不能假设真正始终为false
:编译器不能排除您为某种类型添加部分特化以使dependent_false<...>::value
true
。
回顾这个老问题,可能有一个更简单的答案:将重载标记为已删除。
template <typename T>
auto Function(T value) -> std::enable_if<someCondition, int>
{
// this is the function I want to call
}
template <typename... T>
int Function(T...) = delete;
这不完全相同,因为这允许呼叫者检查例如良好的形状。 Function(int, int)
而不是强制错误,但它更具可读性,并且通常 希望 希望确切的行为不会出现错误,除非实际使用该函数,而不仅仅是引用
答案 1 :(得分:0)
只是在公认的答案上做些扩展:
我们可以另外定义以下内容
template <class... T>
inline constexpr bool dependant_false_v = dependant_false<T...>::value;
当时的用法是
template <typename... T>
int Function(T...)
{
static_assert(dependent_false_v<T...>, "you are passing the wrong arguments!");
}
看起来更干净的IMO,并且写作时间更短。
使用C ++ 17,我们甚至可以摆脱SFINAE enable_if
的限制,并通过constexpr if
将所有内容合并到一个函数中:
template <typename T>
auto Function(T value)
{
if constexpr(someCondition) {
// Code for your function
} else {
static_assert(dependent_false_v<T>, "you are passing the wrong arguments!");
}
}