Я пытался сделать свой код менее раздутым при работе с Windows API, заменив двухстрочные, мало чем отличающиеся
TEMP t{0,1,2}; // let's say it's struct TEMP {int a; int b; int c}
SomeVeryVerboseFunctionName(&t);
с остротами
SomeVeryVerboseFunctionName(&TEMP{0,1,2});
но наткнулся на ошибку:
выражение должно быть lvalue или указателем функции.
После многих попыток я наконец придумал код, который компилируется (MSVS 2013u4):
SomeVeryVerboseFunctionName(&(TEMP) TEMP{0,1,2});//explicit cast to the same type!
Чтобы лучше понять, зачем нужен бросок, я создал простой тестовый проект:
#include <stdio.h>
struct A
{
int a;
int b;
A(int _a, int _b) : a(_a), b(_b) {};
};
struct B
{
int a;
int b;
};
template <typename T> void fn(T* in)
{
printf("a = %i, b = %i\n", in->a, in->b);
}
int main()
{
fn(&A{ 1, 2 }); //OK, no extra magick
/* fn(&B {3, 4}); //error: expression must be an lvalue or function designator */
fn(&(B)B{ 3, 4 }); //OK with explicit cast to B (but why?)
}
и обнаружил, что если какая-то структура T
имеет явный конструктор (как A
в приведенном выше коде), то можно взять адрес инициализированного фигурными скобками временного типа T
и передать его функции, которая принимает указатель T*
, но если у него его нет (например, B
), то возникает указанная ошибка, и ее можно преодолеть только путем явного приведения к типу T
.
Итак, вопрос: почему B
требует такого странного приведения, а A
нет?
Обновлять
Теперь, когда ясно, что обработка rvalue как lvalue является расширением/функцией/ошибкой в MSVS, кто-нибудь хочет притвориться, что это на самом деле функция (достаточно используемая MS для ее поддержки с 2010 года), и уточнить, почему временные файлы A
и B
должны передаваться разными способами, чтобы удовлетворить компилятор? Это должно быть как-то связано с конструктором A и его отсутствием у B...
testbench.cpp:23:13: error: taking address of temporary [-fpermissive] fn(&A {1, 2});
иtestbench.cpp:25:17: error: taking address of temporary [-fpermissive] fn(&(B) B {3, 4});
- person sunny moon   schedule 09.07.2015fn(&A{ 1, 2 })
компилируется?A
здесь не кастуется... - person sunny moon   schedule 09.07.2015A
иB
отличаются только конструкторами, функции, принимающие временные значения их типов, могут быть скомпилированы благодаря разным расширениям MSVC. Какая фундаментальная разница междуA
иB
заставляет компилятор обращаться с ними по-разному? Извините, я совсем потерялся. - person sunny moon   schedule 09.07.2015