1

我目前正在阅读一本关于模板的书,它给出了以下示例:

#include <string>

// note: reference parameters
template <typename T>
inline T const& max (T const& a, T const& b)
{
    return  (a < b)  ?  (b) : (a);
}

int main()
{
    char* a="apple";
    char* p="peach"; 
    ::max(a,p);   // OK, BUT 
    ::max("apple","peach");//  <<<< ERROR IN VISUAL STUDIO 2012, WHY?
}

我不明白为什么 VS2012 说:

错误 C2440:'return':无法从 'const char *' 转换为 'const char (&)[6]'

请有人向我解释一下吗?书上说应该没问题,但这是一本旧书,我还在等待新书。

4

3 回答 3

3

问题在于,在第二种情况下,您T const&被推断为const char(&)[6],这是对 6 个字符数组的引用。

在 VS2012 中,当您使用 进行比较时?:,它会衰减对 的数组引用char*,然后无法将其作为引用返回。GCC 4.7.2 没有表现出这种衰减(参见https://ideone.com/yIBZWi)。

你能试试下面不那么紧凑的版本吗(我手头没有VS2012)?它应该能够通过在 return 中不同时使用 a 和 b 来避免衰减。

template <typename T>
inline T const& max (T const& a, T const& b)
{
    if(a<b)
       return b;
    else
       return a;
}
于 2013-06-26T14:26:35.833 回答
1

错误原因如下:

字符串文字的类型为const char[X],其中 X 是字符串的长度,包括零分隔符。在您的情况下,它是 6,所以总共Tconst char[6].
无法将 C 数组与关系运算符进行比较,因此编译器将“数组应用于指针衰减”,这意味着 in (a < b)、 a 和 b 被视为指针。
似乎 Visual Studio 将衰减应用于整个表达式,即它也将 a 和 b 视为 in 中的指针(b) : (a)
然后整个表达式具有 type char const*,但返回类型是T const&, meaning const char(&)[6],并且指针不能向后转换。我相信这是VS2012中的一个错误。

更新: 这是一个标准引用来支持这是一个错误的说法:
§5.16,4:

如果第二个和第三个操作数是相同值类别的glvalues并且具有相同的类型,则结果是该类型和值类别[...]

旁注1:你包括<string>,这是不可能的。请注意,字符串文字不是std::strings, mostyl 是出于与 C 向后兼容的原因。
旁注 2:您将字符串文字分配给char *,不推荐使用。字符串文字是 type char const[],因此将它们衰减char*为一种特殊性,同样是由于向后兼容的原因。如果您确实将该指针后面的字符串视为非常量并写入它们,您将获得未定义的行为。所以更喜欢char const*,你的编译器无论如何都应该警告你。
旁注 3: 在 C++ 中,指针不是完全有序的。因此,衰减数组的比较,max 函数中指针的含义是实现定义的,您将希望在可移植程序中避免这种情况。无论如何,它没有任何意义,因为它是地址,而不是字符串文字内容。 旁注4:你很幸运“apple”和“peach”的长度相同。如果不是,例如“apples”和“peaches”,编译器会看到 char 类型的文字,const char[7]并且const char[8]不知道T应该是什么:http: //ideone.com/fp2WmJ

于 2013-06-26T14:35:49.483 回答
0

在实例化函数模板max时,模板参数T是从参数推导出来的。在您的示例中,它的类型char const [6]是 6 个字符的数组。

该表达式(a < b) ? (b) : (a)会将(a)和都转换(b)为指针(规则 5.16.6,“数组到指针 (4.2),[...] 标准转换在第二个和第三个操作数上执行”。)

然后编译器将尝试将结果转换char const *为 a T(返回类型),即 a char const[6],因此您的错误。

GCC 没有表现出这种行为,因为如果它们的类型相同,它不会将数组转换为指针,即相同大小的 char 数组。只要两个 char 数组的大小不同,错误仍然会出现。

无论如何,比较 char 数组可能不会像你想的那样工作,所以最好只使用它std::string

于 2013-06-26T14:45:55.433 回答