Search code examples
c++templatesc++17sfinaefunction-templates

Deduct template parameter fail while using if constexpr


I am trying to figure out how the sfinae concept works in C++. But I can't convince the object-type compiler if bool is true or false.

#include <iostream>

class A {
public:
    void foo() { std::cout << "a\n"; }
};

class B {
public:
    void ioo() { std::cout << "b\n"; }
};

template<class T>
void f(const T& ob, bool value = false)
{
    if constexpr (!value) ob.foo();
    else  ob.ioo();
}

int main()
{
    A ob1;
    B ob2;
    f(ob1, true);
    f(ob2, false);
}

Solution

  • You need to let the bool parameter to be part of template. In your case, bool value is a run time parameter.

    By adding the value as non-template parameter, your code can compile:

    template<bool Flag, class T>
    //       ^^^^^^^^
    void f(const T& ob)
    {
        if constexpr (Flag) {
            ob.foo();
        }
        else
            ob.ioo();
    }
    

    and you may call like:

    f<true>(ob1);
    f<false>(ob2);
    

    As a side note, your A::foo() and B::ioo() must be const qualified member functions, as you want to call, with a const objects of each classes inside the f.


    That being said, the bool parameter is redundant if you can use the std::is_same

    #include <type_traits> // std::is_same
    
    template<class T>
    void f(const T& ob)
    {
        if constexpr (std::is_same_v<T, A>) {
            ob.foo();
        }
        else if constexpr (std::is_same_v<T, B>)
            ob.ioo();
    }
    

    Now call needs to be just:

    f(ob1);
    f(ob2);