Reputation: 81
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
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