Неоднозначность построения объекта / прямого объявления функции

StackOverflow https://stackoverflow.com/questions/2275653

Вопрос

Observation: the codes pasted below were tested only with GCC 4.4.1, and I'm only interested in them working with GCC.

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

Я не раз натыкался на инструкцию по построению объекта, которую не понимал, и только сегодня заметил, какую двусмысленность она привносит.Я объясню, как воспроизвести это, и хотел бы знать, есть ли способ это исправить (допускается 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();
}

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

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

Не бери в голову.Это обман Самый неприятный разбор:почему не A a(());работать?.

Спасибо, sbi.

Это было полезно?

Решение

Это известно как «самый неприятный анализ C++».Видеть здесь и здесь.

Другие советы

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

int f1();

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

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

int f2(double );

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

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

ClassType c = ClassType(ArgType());

Ознакомьтесь с часто задаваемыми вопросами по C++ на сайте конструкторы для объяснения и примеры

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

Class c(ArgType {});

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top