Adam Rackis
Adam Rackis

Reputation: 83358

Why does std::enable_if require the second template type?

I have the following function template

template
<
    typename FilterLHS,
    typename FilterRHS,
    typename Of = typename FilterLHS::OfType,
    std::enable_if_t<std::is_base_of_v<Filter<Of>, FilterLHS> && std::is_base_of_v<Filter<Of>, FilterRHS>, int> = 0
>
std::shared_ptr<OrFilter<Of>> operator ||(const std::shared_ptr<FilterLHS> &lhs, const std::shared_ptr<FilterRHS> &rhs)
{
    return std::make_shared<OrFilter<Of>>(OrFilter<Of>{ lhs, rhs });
}

It works fine. My question is, why is the int second argument, and default value of enable_if required? As I understand, especially from this answer, I should just be able to do

template
<
    typename FilterLHS,
    typename FilterRHS,
    typename Of = typename FilterLHS::OfType,
    std::enable_if_t<std::is_base_of_v<Filter<Of>, FilterLHS> && std::is_base_of_v<Filter<Of>, FilterRHS>>
>
std::shared_ptr<OrFilter<Of>> operator ||(const std::shared_ptr<FilterLHS> &lhs, const std::shared_ptr<FilterRHS> &rhs)
{
    return std::make_shared<OrFilter<Of>>(OrFilter<Of>{ lhs, rhs });
}

but when I do that, my template never seems to get enabled.

Upvotes: 0

Views: 325

Answers (1)

Hatted Rooster
Hatted Rooster

Reputation: 36463

If the enable_if would go through, the first snippet would produce:

template<int = 0>

Which is valid.

But this, which is what you would get from snippet 2:

template<void>

Isn't and so SFINAE always kicks in here.

Upvotes: 3

Related Questions