boost :: enable_if для функции-члена, тип возвращаемого значения перегрузки - PullRequest
1 голос
/ 10 июля 2019

Я хочу иметь возможность использовать boost::enable_if для выключения / включения некоторых методов.

Для целочисленных типов я хочу вернуть TypeToReturn из operator() Для других типов я хочу вернуть const TypeToReturn&

Это моя попытка:

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
    }
};

Я получаю ошибки, что эти функции не могут быть перегружены и т. Д.

Я даже не уверен, что эта попытка является шагомхорошее направление.

РЕДАКТИРОВАТЬ: после первого предложения я добавляю код после исправления, все еще вызывает проблему, что "const typename boost :: disable_if ..... не может быть перегружен"

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
    }
};

Ответы [ 2 ]

2 голосов
/ 10 июля 2019

SFINAE применяется к шаблонным методам.Вы не.

В C ++ 11 у нас может быть шаблон по умолчанию для функции, которая обрабатывает это:

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 допускает более простой синтаксис с if constexpr,

и C ++ 20 позволяют requires отказаться от метода благодаря чертам.

В C ++ 03 я бы предложил вместо этого диспетчеризацию тегов:

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>());
    }
};
1 голос
/ 10 июля 2019

Вам необходимо указать тип для enable_if

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

в противном случае значение по умолчанию аннулируется

И чтобы это работало по-настоящему, вам нужно либо самостоятельно создать шаблонные функции оператора, чтобы SFINAE включился, но это не будет работать для c ++ 03, как указано в тегах.

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

Или используйте фиктивную переменную, чтобы операторы отличались параметрами вместо возвращаемого значения. Но все равно сохранив шаблон. Это будет работать для C ++ 03

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

Вы также можете добавить проверку T на int, чтобы выдать ошибку времени компиляции, если это не так.

...