问题
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?
回答1:
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
回答2:
N.B. you can also do it without enable_if
(looks cleaner, IMO):
template <typename> struct Traits {
static const bool value = false;
};
template <typename T>
struct Traits<T&> : Traits<T> {};
template <typename T>
struct Traits<T&&> : Traits<T> {};
来源:https://stackoverflow.com/questions/53742648/why-cant-i-add-a-layer-of-abstraction-with-type-lookup-to-strip-references-in-c