问题 为什么我不能在模板中返回数组的第一个元素?


考虑:

#include <iostream>

template <typename T> T getArray( T &arr ) {
    return *arr;
}

int main() {

    int a[] = {5, 3, 6};

    std::cout << getArray(a);

}

它假设打印数组中的第一个元素但它不起作用。这是为什么?

它给了我错误:

error: no matching function for call to 'getArray(int [3])'

9741
2017-08-13 22:03


起源

“这不是没有用” - 你能详细说明吗? - Mysticial
的类型 a 是 int[3],所以的类型 T 是 int[3]。无法从函数返回数组。 - GManNickG
我认为你应该阅读关于指针的C和C ++之间的区别。 - user827992
@Robert Harvey:虽然问题写得不是很好,但我认为这是一个有趣的问题,因为它是纯粹的SFINAE,你不会期望它。 - David Rodríguez - dribeas
@Mysticial:我还没有看到任何以前版本的问题...仍然关闭而没有机会编辑这个问题似乎很苛刻 - David Rodríguez - dribeas


答案:


的类型 a 是 int[3],所以的类型 T 是 int[3]无法从函数返回数组。

在C ++ 11中,您可以这样做:

template <typename T>
auto getArray(T &arr) -> decltype(*arr)
{ 
    return *arr; 
} 

或这个:

// requires <type_traits>

template <typename T>
typename std::remove_extent<T>::type& getArray(T &arr)
{ 
    return *arr; 
} 

在C ++ 03中你可以做到这一点,但它并不完全相同:

template <typename T>
T getArray(T* arr /* not really an array */)
{ 
    return *arr; 
} 

要么:

template <typename T, std::size_t N>
T getArray(T (&arr)[N])
{ 
    return *arr; 
} 

12
2017-08-13 22:12



如果OP想知道如何 remove_extent 可以定义: template<class T> struct remove_extent { typedef typename T type; }; template<class T, size_t N> struct remove_extent<T[N]> { typedef typename T type; }; - Mehrdad
在我看来,这导致两个功能不同的函数模板,因为使用decltype的一个将返回一个引用,而使用remove_extent的那个返回值。 - Johannes Schaub - litb
我是初学者。我知道这些函数应该返回数组中的第一个元素,但我没有得到的是什么 -> decltype(*arr) 和 size_t 假设要做什么? - template boy
@ JohannesSchaub-litb:这是正确的,谢谢! - GManNickG
@ user6607: decltype 为您提供表达式的类型。因为 *arr 有类型 int&,函数返回一个 int&。我们让编译器完成确定要返回的内容的工作。 size_t 是一个无符号整数类型,用于保存事物的大小,包括数组。 - GManNickG


尝试

template <typename T, size_t N>
T getArray( T (&arr)[N] ) {
    return *arr;
}

以便 T 是元素的类型,而不是数组。


2
2017-08-13 22:12





它甚至不能在MSVC ++ 2010 Express上编译。正如我所料,这是因为你使用引用作为参数,标量作为返回值,指针被传递给函数调用。我不知道有关模板的确切规则(即如何确定类型)但该代码必须混淆编译器的地狱。以下代码返回您希望返回的内容。

#include <iostream>

template <typename T> T getArray( T* arr ) {
    return *arr;
}

int main() {

    int a[] = {5, 3, 6};

    std::cout << getArray(a);

}

1
2017-08-13 22:12



在原始代码中,没有指针传递给函数,而是传递给数组。从那以后 T 是一个数组,并且无法返回数组SFINAE正在禁用该模板。重要的是不要把人与坏人混为一谈 数组是一个指针 事情。 - David Rodríguez - dribeas


你能尝试一下:

#include <iostream>

template <typename T> T getArray( T arr[] ) {
    return *arr;
}

int main() {

    int a[] = {5, 3, 6};

    std::cout << getArray(a);

}

1
2017-08-13 22:14



要符合你应该改变的最新标准 iostream.h 至 iostream 并添加该行 using namespace std; 或使用 std::cout。我没有在我的回复中那样跟随你的代码风格。 - André Oriani