2012-08-12 87 views
2

我想寫一個函數,將第一個參數設置爲第二個參數的值。但是,當第二個參數是一個容器類時,我希望它將第一個參數設置爲容器的第一個元素。我發現this問題,它回答了類似的問題,但是,我似乎無法得到它在我的情況下工作。C++函數重載的Iterable類

當我編譯這段代碼時,我得到一個錯誤,說SetVar是不明確的。無論如何要讓功能正常工作嗎?

這是到目前爲止我的代碼...

#include <iostream> 
#include <vector> 
template<typename T1,typename T2> 
static void SetVar(T1& a, const T2 &b, typename T2::const_iterator= T2().begin()){ 
    //Check to make sure b contains an element. 
    if(b.begin()!=b.end()) a=*b.begin(); 
} 
template<typename T1,typename T2> 
static void SetVar(T1& a, const T2 &b,...){ 
    a=b; 
} 
int main(int argc, const char * argv[]) 
{ 
    int x; 
    int y=5; 
    std::vector<int> z; 
    z.push_back(1); 
    z.push_back(3); 
    SetVar(x, y); 
    //Should print 5 
    std::cout<<x<<"\n"; 

    SetVar(x, z);//<---SetVar is ambiguous 
    //Should print 1 
    std::cout<<x<<"\n"; 
    return 0; 
} 

回答

2

將參數傳遞給省略號確實使得函數的重載不如實際參數爲同一個參數的重載,但由於調用中沒有第三個參數,所以不會出現在這裏。

我會用enable_if兩個:

#include <type_traits> 

// Enabled if T2 has `const_iterator` and `begin()`: 
template<typename T1,typename T2> 
auto SetVar(T1& a, const T2 &b) 
    -> typename std::enable_if<std::is_convertible< 
     decltype(std::declval<const T2&>().begin()), 
     typename T2::const_iterator>::value 
    >::type 
{ 
    //Check to make sure b contains an element. 
    if(b.begin()!=b.end()) a=*b.begin(); 
} 

// Enabled if expression 'a=b' is valid. 
template<typename T1,typename T2> 
auto SetVar(T1& a, const T2 &b) 
    -> typename std::enable_if<std::is_assignable<T1, const T2&>::value>::type 
{ 
    a=b; 
} 

它仍然有可能對上述不明確的,但只有在兩個條件都爲真,這意味着一個奇怪的容器或隱式轉換是怎麼回事 - 和這種情況下,我希望編譯器能夠警告我混淆。

+0

優秀的解決方案,但有沒有什麼辦法可以讓這個工作沒有C++ 11的功能? – 2012-08-12 02:50:01

+0

是的,我認爲從'std ::'我用過的所有東西都在Boost一段時間,你可以移動返回類型來擺脫'auto'和trailing-return-types。 – aschepler 2012-08-12 02:52:16

+0

感謝@LucDanton的修復。我知道,在提交之前我應該​​嘗試一下。 – aschepler 2012-08-12 02:54:04

-1

函數模板不能做到專業化。 this is why

+0

-1這完全不正確。非會員模板功能可以是專門化​​的,只是不是部分專業化的。 http://msdn.microsoft.com/en-us/magazine/cc163754.aspx#S2 – 2012-08-12 02:40:39

+1

而這根本不是專業化的。這只是一種超載。專業化聲明總是有兩套'<>'模板參數列表。 – aschepler 2012-08-12 02:44:32

+0

@aschepler我會承認我使用了錯誤的術語,我應該使用過載。 – 2012-08-12 02:47:34