【问题标题】:ambiguous overloaded function differs only by argument's template parameter模棱两可的重载函数仅因参数的模板形参不同
【发布时间】:2019-03-18 23:33:16
【问题描述】:

考虑以下代码:

SmartPointer<Data> Fix(SmartPointer<Data> data)
{
    return { /* Fixed Data */ };
}
SmartPointer<Data> Fix(SmartPointer<DataWrapper> dataWrapper)
{
    return Fix(dataWrapper->Data());    
}

我将如何重写它以使其不会导致“错误 C2668:对重载函数的模糊调用”?

注意:我也希望能够传入一个子类,例如 SmartPointer&lt;SubclassOfDataWrapper&gt;,并将其解析为超类的重载函数。

【问题讨论】:

    标签: c++ c++11 overloading sfinae ambiguous-call


    【解决方案1】:

    检查智能指针类中是否存在模板转换运算符。

    更重要的是,在转换无效的情况下,检查是否有东西要 SFINAE-out 转换运算符。

    转换运算符中的静态断言不会告诉编译器这些重载没有歧义。

    【讨论】:

    • 我明白了......所以如果我有一个特定于 DataWrapper 的方法(即-&gt;Data()),那么我可以使用它来利用 SFINAE。我觉得我们现在离答案越来越近了。
    【解决方案2】:

    感谢Guillaume Racicot提供的提示,我想出了以下解决方案:

    template<typename T>
    SmartPointer<Data> Fix(SmartPointer<T> dataWrapper)
    {
        // Note: only a subclass of DataWrapper would have the method ->Data()
        //            a subclass of Data would not have it (SFINAE principle)
        return Fix( dataWrapper->Data() );
    }
    template<>
    SmartPointer<Data> Fix(SmartPointer<Data> data)
    {
        return { /* Fixed Data */ };
    }
    

    【讨论】:

    • 要正确约束函数,您必须这样做:std::void_t&lt;decltype(std::declval&lt;T&gt;().Data())&gt;* = nullptr 作为第二个模板参数。
    • 这是该约束的应用:godbolt.org/z/7EcmAL 请注意,我将专业化更改为重载以正确执行此操作
    • @GuillaumeRacicot c++11 没有 std::void_t 并且“尝试使用类型的成员”在此处被列为 SFINAE 类型错误:en.cppreference.com/w/cpp/language/sfinae
    • 确实如此。 Here's a C++11 version。它强制转换为 void 而不是使用 std::void_t
    • @GuillaumeRacicot 有什么理由让演员表无效?当我写 decltype(std::declval&lt;T&gt;().Data())* = nullptr 时,它似乎编译得很好
    猜你喜欢
    • 2011-12-19
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 2012-12-09
    • 1970-01-01
    相关资源
    最近更新 更多