Einar
Einar

Reputation: 4933

Fixing third party code: "error: ‘enable_if’ in namespace ‘std’ does not name a template type"

While trying to build a third party application, I found that one of its dependencies (https://github.com/genome/joinx) would not compile cleanly with newer compilers. In the process of tidying it up (the code looks unmaintained since years), I got stuck with a compiler error I can't quite figure out.

The issue is in this file:


#pragma once

// Utilities for comparing things / establishing orderings.

#include <boost/utility/declval.hpp>

///////////////////////////////////////////////////////////////////////////
// Tags for use with enable_if

// Compare objects return an int <0, =0, or >0 to establish an ordering
// (cf. strcmp)
struct CompareBase {};
// ComparePred objects are predicates (e.g., less than)
// (cf. std::less)
struct ComparePredBase {};

template<typename Op>
struct DerefBinaryOp {
    Op op;

    explicit DerefBinaryOp(Op op = Op())
        : op(op)
    {}

    template<typename ValueType>
    auto operator()(ValueType const& x, ValueType const& y) -> decltype(op(*x, *y)) {
        return op(*x, *y);
    }
};

// Given a "Compare" function, convert it to a less than predicate.
template<
          typename T
        , typename = typename std::enable_if<std::is_base_of<CompareBase, T>::value>::type
        >
struct CompareToLessThan : ComparePredBase {
    CompareToLessThan(T cmp = T())
        : cmp(cmp)
    {}

    template<typename U>
    bool operator()(U const& x, U const& y) const {
        return cmp(x, y) < 0;
    }

    T cmp;
};

// Given a "Compare" function, convert it to a greater than predicate.
template<
          typename T
        , typename = typename std::enable_if<std::is_base_of<CompareBase, T>::value>::type
        >
struct CompareToGreaterThan : ComparePredBase {
    CompareToGreaterThan(T cmp = T())
        : cmp(cmp)
    {}

    template<typename U>
    bool operator()(U const& x, U const& y) const {
        return cmp(x, y) > 0;
    }

    T cmp;
};

// This is a helper class that defines relational operators
// (>, <, ==, !=, ...) for simple structs that define value_type
// and have a single member: value_type value;
template<typename T>
struct ValueBasedRelOps {
    friend bool operator<(T const& lhs, T const& rhs) {
        return lhs.value < rhs.value;
    }

    friend bool operator>(T const& lhs, T const& rhs) {
        return lhs.value > rhs.value;
    }

    friend bool operator<=(T const& lhs, T const& rhs) {
        return lhs.value <= rhs.value;
    }

    friend bool operator>=(T const& lhs, T const& rhs) {
        return lhs.value >= rhs.value;
    }

    friend bool operator==(T const& lhs, T const& rhs) {
        return lhs.value == rhs.value;
    }

    friend bool operator!=(T const& lhs, T const& rhs) {
        return lhs.value != rhs.value;
    }
};

And my compiler spews out errors:

/home/einar/Download/Sources/joinx/src/lib/common/RelOps.hpp:34:36: error: ‘enable_if’ in namespace ‘std’ does not name a template type
   34 |         , typename = typename std::enable_if<std::is_base_of<CompareBase, T>::value>::type
      |                                    ^~~~~~~~~
/home/einar/Download/Sources/joinx/src/lib/common/RelOps.hpp:34:45: error: expected ‘>’ before ‘<’ token
   34 |         , typename = typename std::enable_if<std::is_base_of<CompareBase, T>::value>::type
      |                                             ^
/home/einar/Download/Sources/joinx/src/lib/common/RelOps.hpp:52:36: error: ‘enable_if’ in namespace ‘std’ does not name a template type
   52 |         , typename = typename std::enable_if<std::is_base_of<CompareBase, T>::value>::type
      |                                    ^~~~~~~~~
/home/einar/Download/Sources/joinx/src/lib/common/RelOps.hpp:52:45: error: expected ‘>’ before ‘<’ token
   52 |         , typename = typename std::enable_if<std::is_base_of<CompareBase, T>::value>::type
      |                                             ^

I'm unfamiliar with std::enable_if and the previous searches on SO did not yield a solution similar to my problem. What's the exact cause of the error, so I can start working from there to fix it?

Upvotes: 5

Views: 6757

Answers (1)

UKMonkey
UKMonkey

Reputation: 6983

To help you "find the fish" in the future rather than be given a fish:

error: ‘enable_if’ in namespace ‘std’ does not name a template type means that enable_if more than likely is unknown to the compiler at that point of usage.

Searching for std::enable_if will lead you eventually to this link: https://en.cppreference.com/w/cpp/types/enable_if

You will note the line "Defined in header <type_traits>".

This leads to the question "Has this header been included?".

Upvotes: 7

Related Questions