Неоднозначность построения объекта / прямого объявления функции
-
21-09-2019 - |
Вопрос
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.
Другие советы
Давайте немного упростим.
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 по отдельности.