2010-02-16 7 views
7

Observation: the codes pasted below were tested only with GCC 4.4.1, and I'm only interested in them working with GCC.строительства объекта/Forward объявление функции неоднозначность

Здравствуйте,

Это было не только в несколько раз, что я споткнулся в строительстве объекта заявление, что я не понимал, и это было только сегодня что я заметил, какая двусмысленность вводится им. Я объясню, как воспроизвести его, и хотел бы знать, есть ли способ его исправить (разрешен C++ 0x). Вот оно.

Предположим, что существует класс, конструктор которого принимает только один аргумент, а тип этого одного аргумента - это другой класс с конструктором по умолчанию. Например:

struct ArgType {}; 

class Class 
{ 
public: 
    Class(ArgType arg); 
}; 

Если я пытаюсь построить объект типа Class в стеке, я получаю неоднозначность:

Class c(ArgType()); // is this an object construction or a forward declaration 
        // of a function "c" returning `Class` and taking a pointer 
        // to a function returning `ArgType` and taking no arguments 
        // as argument? (oh yeh, loli haets awkward syntax in teh 
        // saucecode) 

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

#include <iostream> 

struct ArgType {}; 
struct Class {}; 

ArgType func() 
{ 
    std::cout << "func()\n"; 
    return ArgType(); 
} 

int main() 
{ 
    Class c(ArgType()); 

    c(func); // prints "func()\n" 
} 

Class c(ArgType funcPtr()) // Class c(ArgType (*funcPtr)()) also works 
{ 
    funcPtr(); 
    return Class(); 
} 

Итак, достаточно примеров. Кто-нибудь может помочь мне обойти это, не делая ничего слишком анти-идиоматического (я разработчик библиотеки, и люди любят идиоматические библиотеки)?

- редактировать

Ничего. Это ошибка Most vexing parse: why doesn't A a(()); work?.

Спасибо, sbi.

+0

Ваш код компилируется для меня с г ++ - бит, который вы думаете, не должны работать? – 2010-02-16 19:30:06

+0

Это не вопрос работы или не работает. Проблема в том, что я просто хотел построить объект типа 'Class' и передать его конструктору объект типа' ArgType', построенный inline. Но он распознает в качестве прямого объявления. Я добавлю код, который хотел бы работать, но не могу, всего секунду. –

+0

Забудь об этом, Нейл. Посмотрите на ответ sbi, это точно моя проблема. –

ответ

5

Это известно как «наиболее неприятный анализ Си ++». См. here, here и here.

1

Основываясь на «++ 0x C разрешено», правильный ответ (возможно) изменить определение к:

Class c(ArgType {}); 

Простой, прямой и возлагает бремя полностью на пользователя библиотеки, не автор!

Редактировать: Да, ctor вызывается - C++ 0x добавляет List-Initialization как однозначный способ разграничения списков инициализаторов. Он не может быть неправильно проанализирован, как в вашем примере, но в противном случае смысл примерно такой же, как если бы вы использовали круглые скобки. См. N3000, третий пункт в соответствии с §8.5.4/3. Вы можете написать ctor, чтобы получить список инициализаторов в виде одного аргумента, или элементы в списке инициализаторов могут быть согласованы с аргументами ctor отдельно.

+0

Подождите ... но это не вызовет конструктор, не так ли? –

+1

Фактически это не представляется приемлемым для GCC 4.4.1. Существуют и другие комбинации: 'Class c {ArgType {}};' или 'Class c {ArgType()};' И добавление не-C++ 0x-версии вызова конструктора: 'Class c ((ArgType())); ' – UncleBens

1

Давайте немного упростим.

int f1(); 

Что это? Компилятор (и я) говорит, что это декларация для функции, возвращающей целое число.

Как насчет этого?

int f2(double); 

Компилятор (и я) заявляю, что это декларация для функции, принимающей двойной аргумент и возвращающая int.

Так вы пробовали это:

ClassType c = ClassType(ArgType()); 

ЗАКАНЧИВАТЬ C++ чаво облегченный на constructors для explanations и примеры