SFINAE不能避免模糊的呼叫

Joh*_*mph 5 c++ inheritance sfinae ambiguous

编译此代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

导致一个模糊的调用错误,因为它doAction是in TestClass<1>TestClass<2>parent类.

main.cpp:33:15:在多个不同类型的基类中找到成员'doAction'

但是std::enable_if不会禁用这种歧义吗?

编辑:

我认为这种含糊不清的真正原因与此问题相同:

为什么具有相同名称但签名不同的多重继承函数不会被视为重载函数?

可以使用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;
}
Run Code Online (Sandbox Code Playgroud)

我不知道这是@skypjack的回答是什么意思,但我还是以其替代方法让它.

sky*_*ack 5

它会(让我说)在替换后删除两个函数中的一个.
无论如何,首先编译器必须决定你在调用它时要使用哪个函数doAction<1>,然后它可以继续替换并最终因为sfinae而抛弃所选择的函数.
在调用时,它们都是有效的候选者,并且调用实际上是模糊的.

请注意,正如@ Peregring-lk在注释中所建议的那样,TestClass<1>::doAction并且TestClass<2>::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;
}
Run Code Online (Sandbox Code Playgroud)