简体   繁体   中英

boost::enable_if on member function, overload return type

I want to be able to use boost::enable_if to turn off/on some methods.

For integral types I want to return TypeToReturn from operator() For other types I want to return const TypeToReturn&

This is my attempt:

template<typename T>
struct Holder{
    typedef T type;
};


template<typename First,
         typename TypeToReturn = typename Holder<First>::type>

struct SuperClass{

    typename boost::enable_if<boost::is_integral<TypeToReturn> >::type 
    operator()(int& someParameterNotImportant) const
    {
        // stuff
    }

    const typename boost::disable_if<boost::is_integral<TypeToReturn> >::type&
    operator()(int& someParameterNotImportant) const
    {
        // stuff
    }
};

I am getting errors that these functions cannot be overloaded etc.

I am not even sure if this attempt is step in good direction.

EDIT: After first suggestion I am adding code after correction, still gives problem that "const typename boost::disable_if..... cannot be overloaded"

template<typename T>
struct Holder{
    typedef T type;
};


template<typename First,
         typename TypeToReturn = typename Holder<First>::type>

struct SuperClass{

    typename boost::enable_if<boost::is_integral<TypeToReturn>, TypeToReturn >::type 
    operator()(int& someParameterNotImportant) const
    {
        // stuff
    }

    const typename boost::disable_if<boost::is_integral<TypeToReturn>, TypeToReturn >::type&
    operator()(int& someParameterNotImportant) const
    {
        // stuff
    }
};

SFINAE applies to template methods. your are not.

In C++11, we can have default template for function to handle that:

template<typename First,
         typename TypeToReturn = typename Holder<First>::type>
struct SuperClass
{
    template <typename T = TypeToReturn>
    typename boost::enable_if<boost::is_integral<T>, T>::type 
    operator()(int& someParameterNotImportant) const
    {
        // stuff
    }

    template <typename T = TypeToReturn>
    const typename boost::disable_if<boost::is_integral<T>, T>::type&
    operator()(int& someParameterNotImportant) const
    {
        // stuff
    }
};

C++17 would allow simpler syntax with if constexpr ,

and C++20 would allows requires to discard the method thanks to traits.

In C++03, I would suggest tag dispatching instead:

template<typename First,
         typename TypeToReturn>
TypeToReturn helper(int& someParameterNotImportant, boost::true_type)
{
// stuff
}

template<typename First,
         typename TypeToReturn>
const TypeToReturn& helper(int& someParameterNotImportant, boost::false_type)
{
// stuff
}


template<typename First,
         typename TypeToReturn = typename Holder<First>::type>
struct SuperClass
{
    typename boost::conditional<boost::is_integral<TypeToReturn>::value,
                                TypeToReturn,
                                const TypeToReturn&>::type 
    operator()(int& someParameterNotImportant) const
    {
        return helper<First, TypeToReturn>(someParameterNotImportant,
                                           boost::is_integral<TypeToReturn>());
    }
};

You need to provide a type to the enable_if

typename boost::enable_if<boost::is_integral<TypeToReturn>, TypeToReturn >::type 

otherwise it defaults to void

And to make it working for real you need to either make operator's template functions by themselves to allow SFINAE to kick in thru this won't work for the c++03 as stated in tags.

template <typename Ret = TypeToReturn>
typename boost::enable_if<boost::is_integral<Ret>,Ret >::type 
operator()(int& someParameterNotImportant) const

Or use dummy variable and make operators differ by the parameters instead of return value. But still keeping it template. This will work for the c++03

template<typename T>
    TypeToReturn operator()(T& someParameterNotImportant, typename boost::enable_if<boost::is_integral<TypeToReturn>,T >::type* = 0) const

You may also add check for the T being int here to issue compile time error if it isn't.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM