Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

enable_if and conversion operator?

Any chance to use enable_if with a type conversion operator? Seems tricky, since both return type and parameters list are implicit.

like image 759
uj2 Avatar asked Jun 19 '10 16:06

uj2


3 Answers

From the little research I did (and ignoring the c++0x comment from Johannes), my answer is that it depends what you want the enable_if for. If you want the conversion operation to T to exist or not from the type T then it seems that the answer is no, there is no way in C++03 (as Ugo said). But if you need the enable_if to change the behavior of the operator depending on the type of T then yes, there is a workaround which is to call an enabled helper function (called to<T> as Matthieu suggested).

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

For the record, I was frustrated with this for several days, until I realized that I wanted enable_if not for SFINAE but for compile-time behavior change. You may also find that this is the real reason for your need for enable_if also. Just a suggestion.

(Please note that this is an answer for the C++98 era)

like image 70
alfC Avatar answered Nov 11 '22 08:11

alfC


dixit the documentation:
There does not seem to be a way to specify an enabler for a conversion operator. Converting constructors, however, can have enablers as extra default arguments.

like image 2
log0 Avatar answered Nov 11 '22 10:11

log0


While I can understand the theoritecal interest in the question, I personally refrain from using conversion operators as much as possible.

The only one I ever use with consistence is the conversion to a pseudo-boolean (using the Safe Bool idiom), for smart-pointers or proxies, and as noted I use a trick to actually prevent the full boolean semantic...

If I ever want to facilitate conversions, I much prefer something along the line of:

template <class T>
T to() const;

which does not suffer from the limitations (in term of signature) of the conversion operator and requires explicit invocation, just because it's a bit clearer.

like image 2
Matthieu M. Avatar answered Nov 11 '22 09:11

Matthieu M.