Home > Enterprise >  Specialize member func for integral template arg with c 17
Specialize member func for integral template arg with c 17

Time:11-24

I'm trying to use std::enable_if_t and std::is_integral_v templates to specialize a mem-func of a class. I read this, but it is about common functions instead of member-function.

I mimic it and write my codes as following, but it does NOT work.

namespace oct {

class Class1 {
    template< typename T> T memf();
};

template< typename T>
std::enable_if_t< std::is_integral_v<T>, T> Class1::memf() {
    std::cout << "Integral." << std::endl;
    return 1;
};

template< typename T>
std::enable_if_t < ! std::is_integral_v<T>, T > Class1::memf() {
    std::cout << "None-Integral." << std::endl;
    return T {};
};

};

Compiling Error Msg:

no declaration matches ‘std::enable_if_t<is_integral_v, T> oct::Class1::memf()

CodePudding user response:

You can do it as shown below:

Version 1

#include <iostream>
#include <type_traits>

namespace oct{
class Class1 {
    public:
        template< typename T>
        std::enable_if_t< std::is_integral_v<T>, T> memf() ;
        template< typename T>
        std::enable_if_t < ! std::is_integral_v<T>, T > memf();
};
}
template< typename T>
        std::enable_if_t< std::is_integral_v<T>, T> oct::Class1::memf() {
            std::cout << "Integral." << std::endl;
            return 1;
        }
template< typename T>
        std::enable_if_t < ! std::is_integral_v<T>, T > oct::Class1::memf() {
            std::cout << "None-Integral." << std::endl;
            return T {};
        }
int main()
{
    oct::Class1 f;
    f.memf<int>();//prints "Integral."
    f.memf<int*>();//prints "Non-Integral."
}

Version 2

#include <iostream>
#include <type_traits>

namespace oct{
class Class1 {
    public:
        template< typename T>
        std::enable_if_t< std::is_integral_v<T>, T> memf() {
            std::cout << "Integral." << std::endl;
            return 1;
        }
        template< typename T>
        std::enable_if_t < ! std::is_integral_v<T>, T > memf() {
            std::cout << "None-Integral." << std::endl;
            return T {};
        }
};

}
int main()
{
    oct::Class1 f;
    f.memf<int>(); //prints "Integral."
    f.memf<int*>();//prints "Non-Integral."
}

Also, note that function templates cannot be partially specialized.

I have also removed unnecessary ; semicolons that you had in your program.

CodePudding user response:

As alternative to SFINAE, you might use if constexpr:

class Class1
{
    template <typename T>
    T memf()
    {
        if constexpr (std::is_integral_v<T>)
        {
            std::cout << "Integral." << std::endl;
            return 1;
        } else {
            std::cout << "Non-Integral." << std::endl;
            return T {};
        }
    }
};
  • Related