Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C++0x allow decltype() in function signature?

Tags:

c++

c++11

This question obviously assume that we don't want to use templates for this type (for whatever reasons).

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
};

The question is : are 1. and 2. allowed and possible (or even specifically defined) in C++0x?

like image 778
Klaim Avatar asked Jan 31 '11 10:01

Klaim


4 Answers

Yes, but with a different syntax:

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

More general:

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

function return type will be the type of EXPRESSION


EDIT

about the case 1 I'm not sure. I don't think is valid, since don't think that mPrice is a valid expression in such context: you're using a non static function member (Product::mPrime) without an object.

My guess is also that if mPrime was a static member it would work.

like image 136
peoro Avatar answered Sep 22 '22 13:09

peoro


All you have to do is declare mPrice and mLabel before you use 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.
};

This compiles fine under g++ 4.4 with -std=c++0x.

Edit The point is, the compiler has to be able to parse function declarations on the first pass. The body of a member function can be compiled after the member declarations have been parsed, but the member declarations themselves have to be immediately intelligible -- otherwise, where does the poor compiler start?

So the type of every member function argument must be known as soon as it is encountered.

like image 26
TonyK Avatar answered Sep 21 '22 13:09

TonyK


vc++ 2010 compiles this w/o errors:


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;}

};

but if I remove dummy default parameters from methods declarations, the error appears again. decltype in return type works only if it also appears in some function parameter (???)

(Sorry, I understand that it should be a comment, but it's seems interesting and it's not convinient to put code into comments)

like image 34
user396672 Avatar answered Sep 23 '22 13:09

user396672


AFAIK this is not legal since the instance variables are not in scope at the points you use them.

Consider what would happen if you had the following variables declared before your class:

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

In the function decleration mPrice would bind to the global variable rather than the instance member.

Both g++ 4.5 and VS10 refuse to compile your code since mPrice and mLabel are out of scope.

However this seems to be inconsistent with default parameters.

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

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

This gives me a compilation error:

invalid use of non-static data member 'Product::mPrice'

like image 33
Motti Avatar answered Sep 22 '22 13:09

Motti