enable_if 不能用于禁用此声明

enable_if cannot be used to disable this declaration

我显然没有足够的 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

在与模板声明对应的行上。到底是怎么回事?我一直使用这种语法来启用和禁用我的模板 类 并且它总是在实例化行而不是在声明行抛出错误..

你能不能迂腐地解释一下我这里做错了什么?

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

A non-type template-argument is dependent if its type is dependent or the constant expression it specifies is value-dependent.

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

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

This metafunction is a convenient way to leverage SFINAE to conditionally remove functions from overload resolution based on type traits and to provide separate function overloads and specializations for different type traits. std::enable_if can be used as an additional function argument (not applicable to operator overloads), as a return type (not applicable to constructors and destructors), or as a class template or function template parameter.

您不能使用它来启用或禁用 [​​=12=] 或 struct

也许您正在寻找类似的东西:

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

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

I need an error to be thrown when trying to instantiate something like `more_than_99 <0> x;' on the line where I try to instantiate it. Something like "hey, this type doesn't exist".

这样的怎么样?

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> 的恶意实例化。

如果您有 class 专业化(或函数重载),

enable_if 是有意义的。它用于根据模板参数在一种实现和另一种实现之间选择,如果不满足条件则不会触发错误。

想法是"enable this specialization if the condition is met, otherwise fall back to the non-specialized version"。

在你的情况下,你可能想要这样的东西:

#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
}

使用静态断言:

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;