enable_if to conditionally include member functions

c++, c++11, enable-if, templates

Solution

`std::enable_if` needs to depend on a parameter of the member template itself.

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 will work as expected.

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;

Problem

I have a templated class, whose types are iterators. I want to enable/disable particular member functions depending on the iterator_category of my template parameter. In particular, I want to enable `operator--` if the template parameter is a bidirectional iterator. My attempt was this: ``` typename std::enable_if< std::is_base_of<std::bidirectional_iterator_tag, MyTemplateParameter>::value, MyType&>::type operator --() { //do work return *this; } ``` Clang tells me (roughly): `error: no type named 'type' in 'std::__1::enable_if<false, MyTemplateParameter>'; 'enable_if' cannot be used to disable this declaration` Is there a way to accomplish what I'm trying? Here's the example in some context: ``` #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; ^ */ } ```

Original source

Related problems