Сбой вывода аргументов шаблона в MSVC: ошибка? - PullRequest
7 голосов
/ 15 октября 2011

Следующее не удается скомпилировать на компиляторе VC ++ 8.0 с ошибкой (я еще не пробовал на последнем компиляторе Visual Studio.)

ошибка C2440: «возврат»: невозможно преобразовать из «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 (&)[6].

Насколько я знаю, когда применяется оператор <, массив должен исчезнуть до указателя. Так может ли эта ошибка быть из-за возможной ошибки?

Ответы [ 2 ]

3 голосов
/ 15 октября 2011

Это, безусловно, ошибка в компиляторе Microsoft.

Вот одна большая разница в C и C ++.

 e0 ? e1 : e2

В C ++ условное выражение создает lvalue , , если хотя бы одно из выражений во второй части (после '?') не является rvalue, тогда как в C условное выражение всегда выдает rvalue , несмотря ни на что. Это означает, что следующий код совершенно допустим в C ++, но это ошибка в C:

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

В C ++ это не даст никакой ошибки, именно потому, что выражение (a<b?a:b) является выражением lvalue, так что вы можете поместить его слева от присваивания.

Теперь вернемся к исходному вопросу. В вашем случае a и b являются массивами типа char (&) [6], а выражение a<b? a : b должно выдавать lvalue, поскольку нет необходимости в преобразовании массив-указатель . Но в компиляторе Microsoft, кажется, есть преобразование массива в указатель .

Чтобы проверить это, можно написать это:

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;
}

И это также дает без ошибок (в GCC), что означает, что выражение, которое вы передаете f(), является массивом, а не указателем.

0 голосов
/ 15 октября 2011

Насколько я знаю, когда применяется оператор <, массив должен исчезнуть до указателя.

В этом и проблема, он превращается в const char *, но затем пытается преобразовать это в const char [8] для возвращаемого значения.

Я не уверен, что стандарт говорит об этом, но если вы измените его на любой:

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

или

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

Тогда параметр шаблона T будет char * вместо char [8].

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...