Reputation: 76276
I have a template class that needs to be specialized for template parameters that contain specific typedef. So I need two definitions, one for the case it has the typedef and another for the case it does not.
My problem is that I don't see how to negate the SFINAE. I could obviously eliminate the special case for the non-special parameter, but I don't know how to eliminate the default for the special parameter.
So I tried partial specialization like this:
struct NormalType { };
struct SpecialType { typedef int special; };
template <typename T, typename IsSpecial = void>
struct DetectSpecial {
void detected() { std::cout << "Not special...\n"; }
};
template <typename T>
struct DetectSpecial<T, typename T::special> {
void detected() { std::cout << "Special!\n"; }
};
but the specialization does not get used (as SSCCE on ideone).
I have also considered using enable_if
, but I don't see how to use it for well-formed vs. non-well-formed expressions rather than true/false.
What is the simplest way to define DetectSpecial
differently for types that contain specific typedef (the value of the typedef may be anything; it's presence is important)?
Oh, I am still stuck with some C++03 compilers. I don't think anything change in SFINAE anyway.
Upvotes: 2
Views: 602
Reputation: 217283
Following may help: (C++11) https://ideone.com/XISlZ6 (C++03) https://ideone.com/egKrcL
#include <cstdint>
template <typename U>
class has_special
{
private:
template<typename T> struct dummy;
template<typename T>
static std::uint8_t check(dummy<typename T::special>*);
template<typename T> static std::uint16_t check(...);
public:
static
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t);
};
Upvotes: 1
Reputation: 39121
The minimal change required is to insert some expression in the specialization that is dependent on T::special
and yields void
(to match the default argument). For example:
template<class T>
struct void_alias
{
typedef void type;
};
template <typename T>
struct DetectSpecial<T, typename void_alias<typename T::special>::type> {
void detected() { std::cout << "Special!\n"; }
};
Upvotes: 3