【问题标题】:enable_if to conditionally include member functionsenable_if 有条件地包含成员函数
【发布时间】:2014-02-05 05:16:58
【问题描述】:

我有一个模板类,它的类型是迭代器。我想根据我的模板参数的 iterator_category 启用/禁用特定的成员函数。特别是,如果模板参数是双向迭代器,我想启用operator--。我的尝试是这样的:

    typename std::enable_if<
       std::is_base_of<std::bidirectional_iterator_tag,
                    MyTemplateParameter>::value,
    MyType&>::type
    operator --() {
    //do work
    return *this;
  }

Clang 告诉我(大致):error: no type named 'type' in 'std::__1::enable_if&lt;false, MyTemplateParameter&gt;'; 'enable_if' cannot be used to disable this declaration

有没有办法完成我正在尝试的事情?

这是某些上下文中的示例:

    #include <iterator>
    #include <type_traits>

    template <typename TagType> 
    class test {
      public:
      typename std::enable_if<
         std::is_base_of<std::bidirectional_iterator_tag,
                        TagType>::value,
        test>::type
      operator --() {
         return *this;
      }

    };

    int main(){

      test<std::random_access_iterator_tag> t1;
      test<std::forward_iterator_tag> t2;

    /*
    breakTemps.cpp:13:2: error: no type named 'type' in 'std::__1::enable_if<false,     test<std::__1::forward_iterator_tag> >'; 'enable_if' cannot be used to disable this declaration
            std::is_base_of<std::bidirectional_iterator_tag,
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    breakTemps.cpp:25:35: note: in instantiation of template class 'test<std::__1::forward_iterator_tag>' requested here
       test<std::forward_iterator_tag> t2;
                                       ^
    */

}

【问题讨论】:

  • 注意:MyTemplateParameter 是类模板参数

标签: c++ templates c++11 enable-if


【解决方案1】:

std::enable_if 需要依赖于成员模板本身的一个参数。

template <typename TagType>
class foo
{
public:
    template <typename U = TagType>
      typename std::enable_if<
         std::is_base_of<std::bidirectional_iterator_tag,
                        U>::value,
        foo>::type
      operator --() {
         return *this;
      }
};

SFINAE 将按预期工作。

int main() {
  foo<std::random_access_iterator_tag> f;
  foo<std::forward_iterator_tag> f2;
  --f; // fine
  --f2;
}

main.cpp:24:3: error: no match for 'operator--' (operand type is 'foo<std::forward_iterator_tag>')

--f2;

【讨论】:

  • 使用一元 -- 运算符的风险很低,但是当您在用于 SFINAE 目的的方法中复制类模板参数时,您应该添加 static_assert(std::is_same&lt;U, TagType&gt;::value,"catch invalid explicit specialisation" )
  • 那行得通。这似乎是一种奇怪的限制。为什么这个标准会让你跳过那个圈子?
  • @BenJones 没有 template 函数类型替换,没有替换失败。该技术基于模板类型替换失败的副作用:如果Vector=int 被替换,template&lt;class Vector&gt; typename Vector::iterator abs( Vector const&amp; ) 将导致构建失败。 SFINAE 说这种错误应该只是从考虑中删除过载。实际上,C++ 用户正在入侵一个不打算做其他事情的系统,这就是 SFINAE 有点尴尬的原因。传入的概念......旨在做到这一点!
猜你喜欢
  • 2011-10-21
  • 1970-01-01
  • 2022-11-11
  • 1970-01-01
  • 2020-12-17
相关资源
最近更新 更多