Samaursa
Samaursa

Reputation: 17271

Choosing template specialization of a base type with derived types

Is it possible to have the template specialization of a base type chosen for the derived types? If not, what is a possible solution to the following without having to specialize for each derived type?

NOTE: This is a simplified version of our validator. Different types have different validation requirements

template <typename T>
class IsValid_Executor
{
public:
    auto IsValid(const T& InObj) -> bool = delete;
};

class Bar { };
class Foo : public Bar { };

template <>
class IsValid_Executor<void*>
{
public:
    auto IsValid(const void* InObj)
    {
        return InObj != nullptr;
    }
};

template <>
class IsValid_Executor<Bar*>
{
public:
    auto IsValid(const Bar* InObj)
    {
        return InObj != nullptr;
    }
};

template <typename T>
bool IsValid(const T& InObj)
{
    return IsValid_Executor<T>{}.IsValid(InObj);
}

int main()
{
    Bar* b;

    IsValid(b); // compiles

    Foo* f;

    IsValid(f); // error: use of deleted function
    IsValid_Executor<void*>{}.IsValid(f); // compiles
    IsValid_Executor<decltype(f)>{}.IsValid(f); // error: use of deleted function - why isn't the void* OR the Bar* overload chosen?
    IsValid_Executor<Bar*>{}.IsValid(f); // compiles - however, I cannot know in the `IsValid<T>` function to choose Bar*
}

Upvotes: 2

Views: 181

Answers (1)

songyuanyao
songyuanyao

Reputation: 173034

You can use partial specialization for all the derived classes of Bar.

template <typename T, typename = void>
class IsValid_Executor
{
public:
    auto IsValid(const T& InObj) -> bool = delete;
};

then

template <typename D>
class IsValid_Executor<D*, std::enable_if_t<std::is_base_of_v<Bar, D>>>
{
public:
    auto IsValid(const Bar* InObj)
    {
        return InObj != nullptr;
    }
};

LIVE

Upvotes: 1

Related Questions