Syntax patterns enable_if

I used enable_ifin this rough order with various versions of GCC (prior to 5.2):

template< bool b, std::enable_if_t< b >... >
void fn() { std::cout << 1 << std::endl; }
template< bool b, std::enable_if_t< !b >... >
void fn() { std::cout << 2 << std::endl; }
// ...
fn< true >();
fn< false >();

But, as it turns out, Clang 3.7 does not accept this (the "fn" call is ambiguous ").

Q1. Who is right and why?

There are, of course, other ways to do this, but I kinda don't like it

template< bool b >
std::enable_if_t< b, void > fa() { std::cout << 1 << std::endl; }
// ...

and its ilk in order to make the normal parts of the function signature less readable, and

template< bool b, std::enable_if_t< b, int > = 0 >
void fd() { std::cout << 1 << std::endl; }
// ...

to include irrelevant elements (types and values).

Q2. What other (correct, more readable, less hacker / weird) ways to use enable_if/ enable_if_tare there?

+4
source share
3 answers

14.1/p7 [temp.param] (Emphasis Mine):

, , , void.

, . , GCC .

:

template< bool b, std::enable_if_t< b, int>... >
void fn() { std::cout << 1 << std::endl; }
template< bool b, std::enable_if_t< !b, int>... >
void fn() { std::cout << 2 << std::endl; }

, . -, , . , .

, 23840.

, / / , :

template< bool b, std::enable_if_t< b, int> = 0 >
void fn() { std::cout << 1 << std::endl; }
template< bool b, std::enable_if_t< !b, int> = 0 >
void fn() { std::cout << 2 << std::endl; }
+3

, enable_if . , counter-idomatic.

:

template <bool> void fn();
template <> void fn<true>() { std::cout << "true fn\n"; }
template <> void fn<false>() { std::cout << "false fn\n"; }
+3

Q2. (, , /) enable_if/enable_if_t ?

, ?

#include <iostream>
#include <type_traits>


template< bool b >
auto fn() -> std::enable_if_t<b>
{
    std::cout << 1 << std::endl;
}

template< bool b>
auto fn() -> std::enable_if_t<!b>
{
    std::cout << 2 << std::endl;
}
// ...


auto main() -> int
{
    fn< true >();
    fn< false >();
    return 0;
}

, :

#include <iostream>
#include <type_traits>

template <bool b> using When = std::enable_if_t<b, bool>;
template <bool b> using Unless = std::enable_if_t<!b, bool>;

template< bool b, When<b> = true>
void fn2()
{
    std::cout << 1 << std::endl;
}

template< bool b, Unless<b> = true>
void fn2()
{
    std::cout << 2 << std::endl;
}

auto main() -> int
{
    fn2< true >();
    fn2< false >();
    return 0;
}

... - ?

template <bool b> using Eval = std::integral_constant<bool, b>;

template<bool b>
void fn3()
{
    struct fn3_impl
    {
        static void when(std::true_type)
        {
            std::cout << 1 << std::endl;
        }

        static void when(std::false_type)
        {
            std::cout << 2 << std::endl;
        }
    };

    fn3_impl::when(Eval<b>());
}
+1

Source: https://habr.com/ru/post/1618171/


All Articles