Search code examples
c++c++11type-traitsperfect-forwarding

Why can't I add a layer of abstraction with type lookup to strip references in C++?


This is kind of a followup question to

Why can't I use traits with forwarding references in C++?

which has been correctly answered. However I tried my own solution below

https://godbolt.org/z/X7dBz1

#include <type_traits>

template <typename T, typename enable = void> struct Traits {
    static const bool value = false;
};

template <typename T> struct Traits<T,std::enable_if<std::is_reference<T>::value>> {
    static const bool value = Traits<typename std::remove_reference<T>::type>::value;

};

struct Zip{};
template <> struct Traits<Zip,void> {
    static const bool value = true;
};

template <typename E>
void Execute(E && e){
    static_assert(Traits<E>::value);
}

int main(){
    auto z = Zip();
    Execute(z);
}

the theory being that if the correct specialisation fails then the next most specialized will be the one that matches based on if T is a reference. If this matches then the reference is stripped and we recurse hopefully getting a match. But this does not seem to work. Is there a way to fix this that keep the spirit of my attempt?


Solution

  • You are misusing std::enable_if. As written, your Traits struct is specialized on std::enable_if itself, not its result. You need to access the nested ::type type alias:

    typename std::enable_if<std::is_reference<T>::value>::type
    // or
    std::enable_if_t<std::is_reference<T>::value>
    

    live example on godbolt.org