2016-11-12 53 views
5

避免编译此代码调用不明确:不SFINAE

#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<1>TestClass<2>父类。

的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; 
} 

我不知道它是不是wh在@skypjack答案的意思,但我让它无论如何其替代方法。

回答

5

它会(让我说)下降替代后的两个功能之一。
无论如何,首先编译器必须决定当你调用它时打算使用哪个函数作为doAction<1>,然后它可以继续进行替换并最终抛弃所选择的函数,因为sfinae。
在调用的时候,他们都是有效的候选人,并且调用实际上是不明确的。

请注意,正如@ Peregring-lk在注释中所建议的,TestClass<1>::doActionTestClass<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; 
} 
+0

为了更加清楚,添加'TestClass的<1> :: doAction'和'TestClass的<2> :: doAction'是两个不同的功能,而不是相同功能的重载,这是误解的常见原因。 –

+0

@ Peregring-lk完成。谢谢。 – skypjack