2016-11-12 48 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