raskolnikov
raskolnikov

Reputation: 81

C++ template: cannot combine with previous 'type-name' declaration specifier

I'm writing a utility function to look for elements in containers like so:

#include <algorithm>
#include <type_traits>

// Helper to determine whether there's a const_iterator for T.
template <typename T>
struct hasConstIt {
private:
    template<typename C> static char test(typename C::const_iterator*);
    template<typename C> static int test(...);

public:
    enum { value = sizeof(test<T>(0)) == sizeof(char) };
};

// Check if a container contains an element.
template <typename Container>
typename std::enable_if<hasConstIt<Container>::value, void>::type
struct In {
    const Container & container;
    typename Container::value_type const & element;

    In(const Container & container, typename Container::value_type const & element) :
        container(container), element(element) {}

    bool operator()() const {
        return std::find(container.begin(), container.end(), element) != container.end();
    }
};

I took my solution from this stackoverflow question.

When I compile the code with g++ -std=c++17 I get the following error messages:

./util.hpp:19:1: error: cannot combine with previous 'type-name' declaration specifier
struct In {
^
./util.hpp:18:1: error: declaration does not declare anything [-Werror,-Wmissing-declarations]
typename std::enable_if<hasConstIt<Container>::value, void>::type

I have been looking for a solution but couldn't find one. Why is the compiler complaining here?

Upvotes: 2

Views: 907

Answers (1)

bipll
bipll

Reputation: 11940

template <typename Container>
typename std::enable_if<hasConstIt<Container>::value, void>::type
struct In {

is wrong. This is done as either

template <class Container, typename = std::enable_if_t<hasConstIt<Container>::value>>
struct In {

in old-fashioned C++11. Note the second argument: it has default value and is normally never specified explicitly but prevents instantiation when the predicate is unsatisfied.

Or, more modern,

template<class Container> requires (hasConstIt<Container>::value) struct In {

in C++20.

Upvotes: 3

Related Questions