Наиболее неприятный синтаксический анализ: почему `g ((f ()));` не вызывает конструктор `f` по умолчанию и передает результат в ctor` g`, который принимает `f`?

Это не дубликат Самый неприятный разбор: почему не A a (()); Работа?, который основан на разборе в виде A a(());, чья OP мысль сможет построить по умолчанию A объект, используя дополнительный набор скобок.

Напротив, мой вопрос о 2 классах, f а также g, где f имеет конструктор по умолчанию и gКтор принимает f, Я хочу позвонить gКтор с временным f аргумент, все без использования единого синтаксиса инициализации. Есть std::cout заявление в gctor, поэтому отсутствие вывода означает объявление функции вместо g создание объекта. Я прокомментировал пример кода с 3 цифрами в комментариях. # 1 и # 2 были скомпилированы с # 3 закомментированными, и наоборот:

#include <iostream>
struct f {};
struct g {
g(f) { std::cout << "g's ctor\n"; }
};
int main() {
// -----Output-----
g( f() );             // #1: function declaration; expected
g( ( f() ) );         // #2: also a function declaration; UNEXPECTED
// g myG( ( f() ) );  // #3: "g's ctor" ONLY if #1 & #2 are commented out;
//     ^ ... linker error otherwise
}

# 1: Я думал, что # 1 объявляет анонимную функцию, которая возвращает g и принимает указатель на функцию, которая принимает 0 аргументов и возвращает f, Я ошибся?

# 2: Итак, я думал, что дополнительный набор скобок в # 2 заставит заключенное содержимое быть оцененным как вызов функции, а именно вызов fctor по умолчанию. Но это все еще объявление функции. Зачем?

# 3: вариант # 2, где разница — добавленное имя экземпляра # 3 myG, # 3 создает объект, если # 1 и # 2 закомментированы. В противном случае я получаю эти ошибки в VC12:

error LNK2019: unresolved external symbol "struct g __cdecl f(void)" (?f@@YA?AUg@@XZ) referenced in function _main а также

fatal error LNK1120: 1 unresolved externals,

и эта ошибка в g ++ 4.8: undefined reference to 'f()'

Что они имеют в виду, и почему я их получаю?

Почему # 3 является экземпляром объекта, только когда экземпляр назван?

Как получить желаемый эффект создания экземпляра, не называя экземпляр или используя единую инициализацию?

4

Решение

Первый объявляет функцию с именем f не принимает параметров и возвращает g,

     g( f() );
//  ^     ^  redundant set of parentheses

Второй — тот же, с еще одним избыточным набором скобок (помните, что вы можете иметь столько объявлений тех же функций, сколько пожелаете). Хотя они не всегда бесполезны. Они нужны, скажем, для объявления функции, которая возвращает указатель на функцию:

// function taking an int and returning
// a pointer to a function that takes a char
// and returns a g
g ( *f(int) )(char);
//^         ^ needed, syntax error without them

Что касается третьего:

Когда # 1 и # 2 есть, у вас есть объявление функции для f в mainа также g myG( ( f() ) ); анализируется как объявление объекта типа gпо имени myG и инициализируется в результате вызова функции. Вы получаете ошибку компоновщика, потому что нет определения для f,

Когда # 1 и # 2 закомментированы, тип f видно, и устранение неоднозначности с круглыми скобками:

g myG( ( f() ) )
//     ^     ^   these force an expression

Без этой пары вы получили бы другое объявление функции.

То, что вы хотите, это:

   ( g(f()) );
// ^        ^  must be an expression as declarations can't be parenthesized

или что-то менее Lisp-ы: static_cast<g>(f());

7

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]