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

C++ C++;0x是否允许函数签名中的decltype()?,c++,c++11,C++,C++11,这个问题显然假设我们不想为这种类型使用模板(无论出于什么原因) 问题是:你1。和2.在C++0x中允许和可能(甚至是专门定义的)?是,但使用不同的语法: auto price() -> decltype(mPrice) { return mPrice; } auto price() -> decltype(mPrice) { return mPrice; } 更一般的: auto function( ... ) -> decltype(EXPRESSION) ... 函数返

这个问题显然假设我们不想为这种类型使用模板(无论出于什么原因)


问题是:你1。和2.在C++0x中允许和可能(甚至是专门定义的)?

是,但使用不同的语法:

auto price() -> decltype(mPrice) { return mPrice; }
auto price() -> decltype(mPrice) { return mPrice; }
更一般的:

auto function( ... ) -> decltype(EXPRESSION) ...
函数
返回类型将是
表达式的类型


编辑

关于案例1,我不确定。我认为这是无效的,因为不要认为在这样的上下文中,
mPrice
是一个有效的表达式:您使用的是一个没有对象的非静态函数成员(
Product::mPrime


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

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(); 
int-mPrice=3;
类产品
{ // ...
intfoo(inti=mPrice){return i;}
};
产品p(5.3,“hi”);

std::cout在使用
decltype
之前,只需声明
mPrice
mLabel

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

编辑关键是,编译器必须能够在第一次通过时解析函数声明。成员函数的主体可以在解析成员声明之后进行编译,但是成员声明本身必须是可立即理解的——否则,糟糕的编译器从哪里开始


因此,必须在遇到每个成员函数参数时立即知道其类型。

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;} }; 类产品 { 私人: 浮动价格; std::字符串标记; 公众: 产品(decltype(mPrice)价格、decltype(mLabel)标签) :mPrice(price),mLabel(label{} 自动定价(decltype(mPrice)*p=NULL)常量->decltype(mPrice){return mPrice;} 自动标记(decltype(mPrice)*m=NULL)常量->decltype(mLabel){return mLabel;} }; 但是,如果我从方法声明中删除伪默认参数,错误会再次出现。返回类型中的decltype仅当它也出现在某些函数参数(???)中时才起作用


(很抱歉,我知道它应该是一个注释,但这似乎很有趣,而且将代码放入注释中并不方便)

您确定吗,我在g++中遇到编译错误,因为变量不在范围内(这很有意义,因为它们是实例变量)。您不回答1。不知道,但选民可能会给出他的理由。我还没有投票表决这个问题,因为它仍然是基于怀疑。我想有人指出如果1。通过引用标准或类似的东西来允许。否决票可能是因为答案完全错误——参见我的答案。(不,不是我!)好吧,我不知道,因为decltype()接受表达式,所以问题是在本例中不计算表达式,但在您的示例中是这样的。所以我要问的是,在decltype()的情况下,它是能够使用这个表达式,还是被明确禁止?酷!这是标准行为还是仅gcc实现行为?据我所知,这是标准行为。@Klaim标准说“晚指定的返回类型对于在声明器id之前指定更复杂的类型最有用”这似乎表明,将decltype放在函数之前是有效的,并且对于更容易(或者需要lamdas)的情况,尾部返回值是可选的@MerickOWA:Klaim从未询问过后期指定的返回类型!这只是peoro介绍的一个骗局,实际上与这个问题无关。我试图指出,在C++0x规范中,有人可能会寻找支持,以证明您的语法是有效的。我曾指出,该标准似乎假定您的语法有效,并添加了尾部返回类型以支持复杂的情况(事实并非如此)。在g++4.4.0下,即使删除了伪默认参数,在-std=c++0x的情况下也可以很好地编译。请参阅以获取证据。@TonyK:我几乎毫无疑问,如果gcc编译了您在答案中给出的代码,它应该编译此代码。错误可能是特定于msvc++的,但是非常奇怪。有趣的是,参数是什么似乎并不重要,只要有一个就行。这个参数可能只是“autoprice(int=0)”,但它仍然有效。因此,这只是微软的又一次失误。 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;} };