2015-08-23 88 views
3

我想寫一個區分數組和指針的函數。這是爲了確定文字字符串的大小而需要的。我試過了:數組指針與數組引用的區別

template<typename Ty> 
void f(const Ty* rhs) { 
    std::cout << __FUNCTION__ << rhs << std::endl; 
} 

template<typename Ty, size_t Dm> 
void f(const Ty(&rhs)[Dm]) { 
    std::cout << __FUNCTION__ << rhs << std::endl; 
} 

int main(int, char*[]) { 
    const char arr0[] = "test2"; 
    const char* ptr = "test3"; 
    const char arr6[6] = "test4"; 
    f("test1"); 
    f(arr0); 
    f(ptr); 
    f(arr6); 
    return 0; 
} 

但是編譯器(VS2013)告訴我這個調用是不明確的。任何提示?

在此先感謝。

+4

,如果你指定哪個函數調用的不明確這將有助於(我可以猜測,但這些信息應該是這個問題。) – juanchopanza

回答

-3

我不相信有可能按照你嘗試的方式去做你正在嘗試的東西。下面的語句評價同一件事:

  • int* var

  • int var[]

它的語法糖的所有問題。此外,向函數頭上的數組添加大小隻會警告用戶期望的數組大小。因此,這兩個也是相等(儘可能的編譯器而言):

  • void f(int* v)

  • void f(int v[8])

+2

請注意,OP期望正確引用數組(void f(int(&v)[8])'),它與void f(int * v)'不同。 – Jarod42

+0

感謝大家澄清此問題並提出建議。我感到很驚訝的是,語言規範要求在重載解析之前數組衰減爲指針。任何人都可以解釋爲什麼這個選擇是由標準委員會做出的? –

+0

@ U.Mann我猜與C風格的代碼的兼容性要求:如果他們收到數組參數,則不希望強制人們將所有函數重寫爲模板。另見[這裏](http://stackoverflow.com/a/4810668/509868)。 – anatolyg

3

遺憾的是,電話是模糊的。

至於解決方法,你可以添加一個額外層:

template<typename Ty> 
void f_pointer(const Ty* rhs) { 
    std::cout << __FUNCTION__ << rhs << std::endl; 
} 

template<typename Ty, size_t Dm> 
void f_array(const Ty(&rhs)[Dm]) { 
    std::cout << __FUNCTION__ << rhs << std::endl; 
} 

template<typename T> 
std::enable_if_t<std::is_array<T>::value> 
f(const T&t) 
{ 
    f_array(t); 
} 

template<typename T> 
std::enable_if_t<!std::is_array<T>::value> 
f(const T&t) 
{ 
    f_pointer(t); 
} 

Live Demo

1

到Jarod42的答案(工作),另一種方法是使用類模板特:

#include <iostream> 
#include <type_traits> 


template <typename T, bool is_array> 
struct f_helper { 
    static void print_type (T& arg) { 
     std::cout << arg << " is an array\n"; 
    } 
}; 

template <typename T> 
struct f_helper<T, false> { 
    static void print_type (T arg) { 
     std::cout << arg << " is not an array\n"; 
    } 
}; 

template <typename T> 
void f (T& arg) { 
    f_helper<T, std::is_array<T>::value>::print_type (arg); 
} 


int main(int, char*[]) { 
    const char arr0[] = "test2"; 
    const char* ptr = "test3"; 
    const char arr6[6] = "test4"; 
    f("test1"); 
    f(arr0); 
    f(ptr); 
    f(arr6); 
    return 0; 
} 

Live demo

0

更改爲參考在函數模板的第二個重載指針:

template<typename T, size_t S> void f(T(&)[S]){ 
    cout << "array with size " << S << "\n"; 
} 

template <typename T> void f(T*&) { 
    cout << "pointer \n"; 
} 

Live Demo