Rodrigo Ruiz
Rodrigo Ruiz

Reputation: 4355

C++ enable_if template class method if it is std::vector<std::vector<Type>>

I'm implementing a flatten() method for a struct that receives an std::vector.

I want the flatten() method to only be available if MyStruct is constructed with an std::vector<std::vector<Type>>, and not when it's constructed with std::vector<Type> (and Type is not an std::vector, of course).

It did manage to make it work, except for CLANG. Depending on how I implement I get different errors.

I'd like to know the proper way of doing this with enable_if.

The signature of my struct should look similar to this:

template <typename Type>
struct MyStruct {

    ...

    // this should only exist if Type is an std::vector
    MyStruct<Type::value_type> flatten() {
        ...
    }

}

Upvotes: 0

Views: 193

Answers (1)

Billy ONeal
Billy ONeal

Reputation: 106530

Why do you need enable_if for this? Plain ol' type deduction is for you:

template <typename T>
MyStruct<vector<T>> flatten(const MyStruct<vector<vector<T>>>& input) {
    // ...
}

EDIT: For your updated question, you really really probably want to use a nonmember here. It is a simpler API for your customers and given what this thing is doing, flatten probably doesn't need access to MyStruct's private bits, and if it doesn't need access to private bits it should be a non-member non-friend.

If for some reason you want to do this thing, you could write a trait for it using a free function, and then static_assert inside, similar to:

http://melpon.org/wandbox/permlink/W0NG1VxX4fuia8kM
or
http://melpon.org/wandbox/permlink/UJZ7qliuAqXLSW4b

#include <vector>
#include <type_traits>

template <typename T>
std::false_type is_vector_of_vector_helper(const T&); // not defined
template <typename T>
std::true_type  is_vector_of_vector_helper(const std::vector<std::vector<T>>&);

template <typename T>
using is_vector_of_vector_t = decltype(is_vector_of_vector_helper(std::declval<T>()));

template <typename T>
struct MyStruct {
    MyStruct<typename T::value_type> flatten() const {
        static_assert(is_vector_of_vector_t<T>::value,
            "Flatten should only be called with MyStruct<vector<vector<T>>>");
        // impl

        return {};
    }
};

Upvotes: 3

Related Questions