【问题标题】:Template argument deduction fails on MSVC: bug?MSVC 上的模板参数推导失败:错误?
【发布时间】:2011-10-14 21:22:45
【问题描述】:

以下在VC++8.0编译器上编译失败,报错(我还没在最新的visual studio编译器上试过。)

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

template <typename T>
inline T const& compare (T const& a, T const& b)
{
    return a < b ? b : a;
}

int main()
{
    ::compare("string1", "string2");
}

在函数模板中,字符串似乎是const char (&amp;)[6]

据我所知,当应用&lt; 运算符时,数组应该衰减为指针。 那么,这个错误可能是因为可能的错误吗?

【问题讨论】:

  • gcc compiles这段代码没有任何问题,所以这一定是MSVC中的一个bug。
  • 无论如何您都不太可能将 C 字符串传递给这样的模板(以比较它们的地址)。
  • 这看起来确实像一个错误,MSVC 说表达式 a &lt; b ? b : a 的类型是 const char * 但它应该是 const char (&amp;)[8]

标签: c++ templates visual-studio-2005


【解决方案1】:

这肯定是 Microsoft 编译器中的一个错误。

这是 C 和 C++ 的一大区别。

 e0 ? e1 : e2

在 C++ 中,condtional-expression 产生 lvalue除非第二部分中的至少一个表达式('?' 之后) 是一个右值,而在 C 中,一个 条件表达式 总是产生 rvalue,无论如何。这意味着,以下代码在 C++ 中完全有效,但在 C 中是错误的:

int a=10, b=20; 
(a<b?a:b) = 100; //ok in C++, but error in C

在C++中不会报错,正是因为表达式(a&lt;b?a:b)是左值表达式,所以你可以把它放在赋值的左边。

现在回到最初的问题。在您的情况下,abchar (&amp;) [6] 类型的数组,而表达式 a&lt;b? a : b 应该产生一个左值,因为不需要 array-to-pointer 转换。但在微软编译器中,似乎有 array-to-pointer 转换。

为了验证它,可以这样写:

template <typename T, int N>
inline void f(T const (&a)[N]) {}

template <typename T>
inline T const& compare (T const& a, T const& b)
{
    f(a < b ? b : a); //is the argument `char*` OR `char (&)[6]`?
    return a < b ? b : a;
}

它给出了no error(在GCC中),这意味着你传递给f()的表达式是一个数组,而不是一个指针。

【讨论】:

  • 虽然对于这种情况是正确的,但您关于条件表达式是否为 lvalue 的陈述太强了。第二个和第三个表达式都可以是 glvalues,但如果它们没有相同的类型并且它们中的任何一个转换为普通类型不会产生直接绑定的 glvalue.
  • @CharlesBailey:我认为您所说的仅适用于 C++11,而 C++03 没有这些概念。我的帖子是关于 C++03,因为 OP 使用的是没有实现 C++11 功能的 MSVS 2008。
  • 很明显,您必须阅读 lvalueglvaluervalueprvalue ,但从根本上说,这在 C++03 中仍然适用。
【解决方案2】:

据我所知,当应用&lt; 运算符时,数组应该衰减为指针。

这就是问题所在,它正在衰减为 const char *,但随后它试图将其转换为 const char [8] 以作为返回值。

我不确定标准对此有何规定,但如果您将其更改为:

compare<char *>("string1","string2");

compare(static_cast<const char *>("string1"),static_const<const char *>("string2"));

那么模板参数T 将是char * 而不是char [8]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 2012-10-26
    相关资源
    最近更新 更多