Question

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.

Was it helpful?

Solution

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"; }
};

OTHER TIPS

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);
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top