不能使用Enable_if来禁用此声明

enable_if cannot be used to disable this declaration

本文关键字:声明 Enable 不能 if      更新时间:2023-10-16

我显然没有足够的SFINAE经验来处理这个问题。实际上,直到现在我的印象是它还可以工作,这种问题在过去的半个小时里开始出现,在我的代码中到处都是。

#include <iostream>
using namespace std;
template <unsigned int N, typename = typename enable_if <N >= 100> :: type> 
struct more_than_99
{
};
int main()
{
    more_than_99 <0> c;
}

No type named 'type' in 'std::__1::enable_if<false, void>'; 'enable_if' cannot be used to disable this declaration

放在模板声明对应的行中。发生了什么事?我一直使用这种语法来启用和禁用我的模板类,它总是在实例化行抛出错误,而不是在声明行。

你能解释一下我哪里做错了吗?

关于为什么错误发生在模板定义而不是实例化时,其他答案是正确的。

我需要在尝试实例化的行上抛出一个错误,例如' more_than_99 <0> x;'。比如"嘿,这个类型不存在"

这样的怎么样?

template <unsigned int N, bool B = (N>=100)>
struct more_than_99;
template <unsigned int N>
struct more_than_99<N,true>
{};
int main()
{
    more_than_99 <0> c; // error: implicit instantiation of undefined template 'more_than_99<0, false>'
}

为了使它更健壮,并试图防止意外实例化more_than_99<0,true>,这也适用于(c++ 11):

template <unsigned int N, bool B>
struct _impl_more_than_99;
template <unsigned int N>
struct _impl_more_than_99<N,true>
{};
template <unsigned int N>
using more_than_99 = _impl_more_than_99<N, (N>=100)>;
int main()
{
    more_than_99 <0> c; // error: implicit instantiation of undefined template '_impl_more_than_99<0, false>'
}

虽然错误消息引用了_impl_类型。

您可以将_impl_隐藏在一个详细的名称空间或其他地方,并且只记录more_than_99别名,就好像它是实际类型一样。

但是,您将无法阻止_impl_more_than_99<0,true>的恶意实例化。

N不是一个依赖的非类型模板参数;[temp.dep.temp]/p2

如果非类型模板参数的类型是依赖的,或者它指定的常量表达式是值依赖的,则该参数是依赖的。

因此,不会发生替换失败,而是直接从格式错误的代码发出错误。

enable_if是有意义的,如果你有一个类专门化(或函数重载)。它用于根据模板参数在一种实现和另一种实现之间选择,如果不满足条件则不会触发错误。

其思想是"如果满足条件则启用此专门化,否则退回到非专门化版本"。

在您的情况下,您可能需要这样的内容:

#include <iostream>
#include <type_traits>
using namespace std;
template<unsigned int N, typename = void >
struct more_than_99
{
    // Implementation if N <= 99
    enum { value = false };
};
template <unsigned int N> 
struct more_than_99<N, typename enable_if <N >= 100> :: type>
{
    // Implementation if N >= 100
    enum { value = true };
};
int main()
{
    cout << more_than_99 <0>::value << endl; //false
    cout << more_than_99 <100>::value << endl; //true
}

From http://en.cppreference.com/w/cpp/types/enable_if:(强调我的)

这个元函数是一种方便的方法,可以利用SFINAE根据类型特征有条件地从重载解析中删除函数,并为不同的类型特征提供单独的函数重载和专门化。std::enable_if可以用作附加的函数实参(不适用于操作符重载)、返回类型(不适用于构造函数和析构函数),或者作为类模板或函数模板形参。

不能启用或禁用classstruct

也许你正在寻找这样的东西:

namespace detail
{
   struct more_than_99 {};
   template <bool> Helper;
   template <> Helper<true>
   {
      using type = more_than_99;
   };
}
template <unsigned int N> struct selector
{
   using type = typename detail::Helper<N >= 100>::type
};
using type = selector<10>::type; // Error.
using type = selector<100>::type; // OK.
                                  // type == detail::more_than_99

使用static assert:

template<unsigned int N>
struct more_than_99
{
  static_assert(N >= 100, "N must be more than 99");
};
 more_than_99<1> m1;

会导致如下编译错误:

testM99.cpp:6:3: error: static_assert failed "N must be more than 99"
  static_assert(N >= 100, "N must be more than 99");
  ^             ~~~~~~~~
testM99.cpp:12:19: note: in instantiation of template class 'more_than_99<1>' 
requested here
  more_than_99<1> m1;