【问题标题】:How to implicitly cast templated constructor arguments?如何隐式转换模板化构造函数参数?
【发布时间】:2019-04-19 15:45:48
【问题描述】:

我正在重载具有不同输入类型的模板类A 的构造函数,用于标量和容器类型参数:

template<typename T>
class A {
public:
    A();
    A(T&& _val) { printf("non-template constructor\n");} ;
    template<typename iT> A(const iT& _cont) { printf("template constructor\n");};

};


int main(int argc, char const *argv[]) {


    A<float> foo1(0.9);                     //template constructor
    A<float> foo2((float)0.9);              //no-template constructor 
    A<float> foo3(std::vector<int>(5,8));   //template constructor


    return 0;
}

但是,有没有办法在隐式可转换类型上调用强制非模板构造函数,例如将double 传递给构造函数A&lt;float&gt;()?

【问题讨论】:

    标签: c++ class templates constructor


    【解决方案1】:

    是的,您可以在构造函数模板中添加 SFINAE 约束:

    template<typename iT,
             std::enable_if_t<!std::is_convertible_v<iT&&, T>>* = nullptr>
    A(const iT&) { printf("template constructor\n"); }
    

    iT&amp;&amp; 可转换为T 时,这会导致推导类型iT 的替换失败,从而从重载集中删除构造函数模板。

    (您需要#include &lt;type_traits&gt; 来获取用于表达约束的各种库工具。)

    【讨论】:

    • A&lt;float&gt; foo1(a); 其中a 是双精度的左值不起作用。只是在 MSVC 中失败了。
    • 太棒了。什么是 C++11 等价物?
    • @joaocandre, typename std::enable_if&lt;!std::is_convertible&lt;iT&amp;&amp;, T&gt;::value&gt;::type*.
    • @joaocandre 试试typename std::enable_if&lt;!std::is_convertible&lt;iT&amp;&amp;, T&gt;::value, void&gt;::type*。顺便说一句,这个答案是有缺陷的。由A(const iT&amp; _cont) 推导将失去价值类别。对于某些用法,您将无法知道参数是否可以转换为T &amp;&amp;
    • @joaocandre 你可以尝试重现godbolt.org 中的错误并在此处分享链接吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-10-23
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    相关资源
    最近更新 更多