Разрешает ли C ++ 0x decltype () в сигнатуре функции? - PullRequest
8 голосов
/ 31 января 2011

Этот вопрос, очевидно, предполагает, что мы не хотим использовать шаблоны для этого типа (по каким-либо причинам).

class Product
{
public:
   Product( decltype(mPrice) price_, decltype(mLabel) label_ )  // 1.
      : mPrice( price_ ), mLabel( label_ )
   {}

   decltype(mPrice) price() const {return mPrice;} // 2.
   decltype(mLabel) label() const {return mLabel;} // 2.


private:

   float mPrice ; // type might later be changed to more acurate floating point abstraction
   std::string mLabel; // type might later be changed by a special localization-oriented string
};

Вопрос: являются 1.и 2. разрешено и возможно (или даже специально определено) в C ++ 0x?

Ответы [ 4 ]

8 голосов
/ 31 января 2011

Да, но с другим синтаксисом:

auto price() -> decltype(mPrice) { return mPrice; }
auto price() -> decltype(mPrice) { return mPrice; }

Более общий:

auto function( ... ) -> decltype(EXPRESSION) ...

function Тип возврата будет тип EXPRESSION


РЕДАКТИРОВАТЬ

по делу 1 Я не уверен.Я не думаю, что это допустимо, поскольку не думаю, что mPrice является допустимым выражением в таком контексте: вы используете нестатический член функции (Product::mPrime) без объекта.

Myтакже можно предположить, что если бы mPrime был статическим членом, он бы работал.

7 голосов
/ 31 января 2011

Все, что вам нужно сделать, это объявить mPrice и mLabel до , которое вы используете decltype:

class Product
{
private:
   float mPrice ;
   std::string mLabel;
public:
   Product( decltype(mPrice) price_, decltype(mLabel) label_ )  // 1.
      : mPrice( price_ ), mLabel( label_ )
   {}

   decltype(mPrice) price() const {return mPrice;} // 2.
   decltype(mLabel) label() const {return mLabel;} // 2.
};

Это прекрасно компилируется в g ++ 4.4 с -std = c++ 0x.

Редактировать Дело в том, что компилятор должен иметь возможность анализировать объявления функций при первом проходе.Тело функции-члена может быть скомпилировано после того, как объявления члена были проанализированы, но сами объявления-члены должны быть немедленно понятны - иначе, где начинается плохой компилятор?

Таким образом, тип каждого аргумента функции-члена должен быть известен, как только он встречается.

2 голосов
/ 31 января 2011

vc ++ 2010 компилирует это без ошибок:


class Product
{
private:

   float mPrice ; 
   std::string mLabel; 
public:
   Product( decltype(mPrice) price_, decltype(mLabel) label_ ) 
      : mPrice( price_ ), mLabel( label_ ){}

   auto price(decltype(mPrice)* p=NULL) const -> decltype(mPrice) {return mPrice;}

   auto label(decltype(mPrice)* m=NULL) const -> decltype(mLabel)  {return mLabel;}

};

, но если я удаляю фиктивные параметры по умолчанию из объявлений методов, ошибка появляется снова.decltype в возвращаемом типе работает только в том случае, если он также присутствует в некотором параметре функции (???)

(Извините, я понимаю, что это должен быть комментарий, но это кажется интересным и неудобно помещать код в комментарии)

1 голос
/ 31 января 2011

AFAIK это не допустимо, поскольку переменные экземпляра не находятся в области действия в точках, в которых вы их используете.

Подумайте, что бы произошло, если бы перед вашим классом были объявлены следующие переменные:

int mPrice;
char mLabel;
class Product
{ /*...*/ };

В функции decleration mPrice будет связываться с глобальной переменной, а не с элементом экземпляра.

И g ++ 4.5, и VS10 отказываются компилировать ваш код, поскольку mPrice и mLabel находятся вне области действия.

Однако это, похоже, не соответствует параметрам по умолчанию.

int mPrice = 3;
class Product
{ // ...
   int foo(int i = mPrice) { return i; }
};

Product p(5.3, "hi");
std::cout << p.foo(); 

Это дает мне ошибку компиляции:

недопустимое использование элемента нестатических данных 'Product :: mPrice'

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...