C ++ 0x是否允许函数签名中的decltype()?

时间:2011-01-31 10:01:03

标签: c++ c++11

这个问题显然假设我们不想使用此类型的模板(无论出于何种原因)。

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。和。允许和可能(甚至特别定义)在C ++ 0x中?

4 个答案:

答案 0 :(得分:8)

是的,但语法不同:

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

更一般:

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

function返回类型将是EXPRESSION

的类型

修改

关于案例1我不确定。我不认为是有效的,因为不要认为mPrice在这种情况下是一个有效的表达式:你使用的是非静态函数成员(Product::mPrime)而没有对象。

我的猜测也是如果mPrime是一个静态成员,它就会起作用。

答案 1 :(得分:7)

您需要做的就是在使用mPrice之前声明mLabeldecltype

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 :(得分:2)

vc ++ 2010编译此w / o错误:


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只有在某些函数参数(???)

中出现时才有效

(对不起,我知道它应该是一个评论,但它似乎很有趣,并且将代码放入评论中并不方便)

答案 3 :(得分:1)

AFAIK这是合法,因为实例变量不在您使用它们的范围内。

考虑如果在课前声明了以下变量会发生什么:

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

在函数中,decleration mPrice将绑定到全局变量而不是实例成员。

g ++ 4.5和VS10都拒绝编译您的代码,因为mPricemLabel超出了范围。

然而,这似乎与默认参数不一致。

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

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

这给了我一个编译错误:

  

无效使用非静态数据成员'Product :: mPrice'