enable_if и оператор преобразования? - PullRequest
11 голосов
/ 19 июня 2010

Есть ли шанс использовать enable_if с оператором преобразования типов?Кажется хитрым, так как тип возвращаемого значения и список параметров неявны.

Ответы [ 4 ]

8 голосов
/ 30 сентября 2011

Из небольшого исследования, которое я провел (и игнорируя комментарий С ++ 0x от Йоханнеса), я отвечаю, что это зависит от того, для чего вы хотите enable_if. Если вы хотите, чтобы операция преобразования в T существовала или отсутствовала в типе T, тогда кажется, что ответ отрицательный, в C ++ 03 нет пути (как сказал Ugo). Но если вам нужно enable_if для изменения поведения оператора в зависимости от типа T, тогда да, есть обходной путь, который заключается в вызове включенной вспомогательной функции (называемой to<T> как Предложил Матье).

#include<iostream>
#include<boost/utility/enable_if.hpp>
#include<boost/type_traits/is_class.hpp>

struct B{
    B(const B& other){}
    B(){}
};

struct A{
    template<class T>
    T to(typename boost::enable_if_c<not boost::is_class<T>::value, void*>::type = 0){
        std::clog << "converted to non class" << std::endl;
        return T(0);
    }
    template<class T>
    T to(typename boost::enable_if_c<boost::is_class<T>::value, void*>::type = 0){
        std::clog << "conveted to class" << std::endl;
        return T();
    }
    template<class T>
    operator T(){
        return to<T>();
    }
};

int main(){
    A a;
    double d = (double)a; // output: "converted to non class"
    B b = (B)(a); // output: "converted to class"
    return 0;
}

Для справки, я был разочарован этим в течение нескольких дней, пока не понял, что хочу enable_if не для SFINAE, а для изменения поведения во время компиляции. Вы также можете обнаружить, что это реальная причина вашей потребности в enable_if. Просто предложение.

(Обратите внимание, что это ответ для эры C ++ 98)

2 голосов
/ 11 января 2013

На самом деле, я нашел способ; мы используем закрытый, неиспользуемый класс, чтобы отметить преобразование, которое не должно существовать, и мы используем boost::mpl::if_, чтобы выбрать, производить ли преобразование в NoConversion или в желаемый тип.

class A {
    class NoConversion { };
    template<class B> operator typename boost::mpl::if_<Cond, B, NoConversion>::type() const;
}
2 голосов
/ 20 июня 2010

Хотя я могу понять теоретический интерес к этому вопросу, я лично воздерживаюсь от использования операторов преобразования в максимально возможной степени.

Единственное, что я когда-либо использую с консистенцией, - это преобразование в псевдобулево (используяидиома Safe Bool), для smart-указателей или прокси, и, как уже отмечалось, я использую трюк, чтобы фактически предотвратить полную булеву семантику ...

Если я когда-нибудь захочу упростить преобразования, я очень предпочитаю что-то вдольстрока:

template <class T>
T to() const;

, которая не страдает от ограничений (с точки зрения подписи) оператора преобразования и требует явного вызова только потому, что она немного понятнее.

2 голосов
/ 19 июня 2010

dixit документация :
Похоже, нет способа указать активатор для оператора преобразования. Однако при преобразовании конструкторов в качестве дополнительных аргументов по умолчанию могут быть активаторы.

...