enable_if 和转换运算符?

发布于 2024-09-05 23:22:48 字数 73 浏览 4 评论 0原文

有机会将 enable_if 与类型转换运算符一起使用吗?看起来很棘手,因为返回类型和参数列表都是隐式的。

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

最美的太阳 2024-09-12 23:22:49

根据我所做的一点研究(并忽略 Johannes 的 c++0x 注释),我的答案是,这取决于您想要 enable_if 的用途。如果您希望从类型 TT 的转换操作存在或不存在,那么答案似乎是否定的,在 C++03 中没有办法(如乌戈说)。但是,如果您需要 enable_if 根据 T 的类型更改运算符的行为,那么是的,有一个解决方法是调用启用的辅助函数(如 Matthieu 建议的那样称为 to)。

#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时代的答案)

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)

暮色兮凉城 2024-09-12 23:22:49

删除文档
似乎没有办法为转换运算符指定启用程序。但是,转换构造函数可以将启动器作为额外的默认参数。

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.

温柔少女心 2024-09-12 23:22:49

虽然我可以理解这个问题的理论意义,但我个人尽可能避免使用转换运算符。

我唯一一致使用的是转换为伪布尔值(使用 Safe Bool 习语),用于智能指针或代理,并且如上所述,我使用一种技巧来实际阻止完整的布尔语义...

如果我如果想要促进转换,我更喜欢这样的东西:

template <class T>
T to() const;

它不受转换运算符(在签名方面)的限制,并且需要显式调用,只是因为它更清晰一些。

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.

夏日浅笑〃 2024-09-12 23:22:49

其实我已经找到办法了;我们使用私有的、未使用的类来标记不应该存在的转换,并使用 boost::mpl::if_ 来选择是否生成 NoConversion 或所需类型的转换。

class A {
    class NoConversion { };
    template<class B> operator typename boost::mpl::if_<Cond, B, NoConversion>::type() const;
}

Actually, I have found a way; we use a private, unused class to mark a conversion that shouldn't exist, and we use boost::mpl::if_ to select whether to produce a conversion to NoConversion, or to the desired type.

class A {
    class NoConversion { };
    template<class B> operator typename boost::mpl::if_<Cond, B, NoConversion>::type() const;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文