【问题标题】:Ambiguous call not avoided by SFINAESFINAE 没有避免模棱两可的电话
【发布时间】:2016-11-12 20:59:55
【问题描述】:

编译这段代码:

#include <iostream>


template <int N>
struct TestClass {
    template <int N2, typename std::enable_if<N2 == N, int>::type = 0>
    void doAction() { std::cout << "TestClass::doAction<" << N << ">();\n"; }
};

struct HostClass : public TestClass<1>, public TestClass<2> {
};


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

    hostClass.doAction<1>();
    hostClass.doAction<2>();

    return 0;
}

导致不明确的调用错误,因为 doAction 同时在 TestClass&lt;1&gt;TestClass&lt;2&gt; 父类中。

main.cpp:33:15:在多个不同类型的基类中发现成员“doAction”

但是std::enable_if 不会消除这种歧义?

编辑:

我认为这种模棱两可的真正原因与这个问题相同:

Why do multiple-inherited functions with same name but different signatures not get treated as overloaded functions?

可以使用using关键字解决歧义,如答案所示:

#include <iostream>


template <int N>
struct TestClass {
    template <int N2, typename std::enable_if<N2 == N, int>::type = 0>
    void doAction() { std::cout << "TestClass::doAction<" << N << ">();\n"; }
};

struct HostClass : public TestClass<1>, public TestClass<2> {
    using TestClass<1>::doAction;
    using TestClass<2>::doAction;
};

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

    hostClass.doAction<1>();    // OK, compile
    hostClass.doAction<2>();    // OK, compile
    //hostClass.doAction<3>();  // OK, doesn't compile : "candidate template ignored: disabled by 'enable_if' [with N2 = 3]"

    return 0;
}

我不知道这是否是 @skypjack 答案的意思,但我还是让它作为替代方法。

【问题讨论】:

    标签: c++ inheritance sfinae ambiguous


    【解决方案1】:

    它会(让我说)删除替换后的两个函数之一。
    无论如何,首先编译器必须决定当您以doAction&lt;1&gt; 调用它时您打算使用哪个函数,然后它可以继续进行替换并最终因为 sfinae 而丢弃所选的函数.
    在调用时,它们都是有效的候选者,并且调用实际上是模棱两可的。

    请注意,正如 @Peregring-lk 在 cmets 中所建议的那样,TestClass&lt;1&gt;::doActionTestClass&lt;2&gt;::doAction 是放置在不同命名空间中的两个不同函数,它们不是同一函数的重载。
    这实际上是一个常见的误解来源。


    您可以通过以下方式轻松解决问题:

    #include <iostream>
    
    template <int N>
    struct TestClass {
        void doAction() { std::cout << "TestClass::doAction<" << N << ">();\n"; }
    };
    
    struct HostClass : public TestClass<1>, public TestClass<2> {
        template<int N>
        void doAction() { return TestClass<N>::doAction(); }
    };
    
    
    int main(int argc, const char * argv[]) {
        HostClass hostClass;
    
        hostClass.doAction<1>();
        hostClass.doAction<2>();
    
        return 0;
    }
    

    【讨论】:

    • 为更清楚起见,请添加 TestClass&lt;1&gt;::doActionTestClass&lt;2&gt;::doAction 是两个不同的函数,而不是同一函数的重载,这是常见的误解来源。
    • @Peregring-lk 完成。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 2016-02-19
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多