【发布时间】:2021-12-27 22:10:29
【问题描述】:
我在 Scott Meyer 的有效 C++ 中读到,对于 T 类型的左值表达式而不是名称,decltype 总是报告T& 的类型,我似乎理解 (explained here too)。但是,我看到 在某些设置下,当 decltype 在类的某种类型 Y 的非静态命名成员变量上被调用时,结果类型是 Y& 而不是 @987654327 @ 这对我来说看起来很不寻常。
以下是以下代码。 背景: 我正在尝试使用 SFINAE 根据返回类型排除模板函数重载。这是完整的代码。
#include<iostream>
#include<stdio.h>
#include<string>
#include<typeinfo>
class foo
{
public:
using type1 = std::string;
std::string someFun();
std::string somestring;
};
//OVERLOAD 1
//Type T must have a function T::size()
template<typename T>
auto testFun(T& t) ->decltype((void) (t.size()),t.somestring)
{
std::string hello1{"helloworld"};
return hello1;
}
//OVERLOAD 2
//Type T must have a function T::someFun()
template<typename T>
// auto testFun(T& t) ->decltype((void) (t.someFun()),t.someFun()) //4
auto testFun(T& t) ->decltype((void) (t.someFun()),t.somestring) //3
{
std::cout<<std::boolalpha;
std::cout<<std::is_same<std::string, decltype(t.somestring)>::value<<std::endl; //5
std::string hello{"helloWorld"};
return hello;
}
int main()
{
foo f1;
testFun(f1);
return 0;
}
说明:
testFun 有 2 个重载(参见 cmets OVERLOAD 1 和 OVERLOAD2)。
在foo 的当前实现中,调用 OVERLOAD2 是因为它期望存在一个函数 someFun,该函数在 foo.xml 文件中声明。此外,此重载的返回类型由decltype((void) (t.someFun()),t.somestring) 给出,它返回类型为t.somestring 的类型,即std::string。但是,当我尝试按原样编译函数时,它给了我编译警告,并且没有创建可执行文件。
warning: reference to local variable 'hello' returned [-Wreturn-local-addr]
std::string hello{"helloWorld"};
这让我相信testFun(params) 的返回类型被推断为std::string& 而不是std::string。为什么会这样?
此外,如果我注释//3 行并取消注释//4,代码编译良好并且//5 行输出true,这确认decltype(t.somestring) 的类型确实不是引用限定的。那么为什么原来的设置(line //3 uncomment , line //4 commented)不起作用?
【问题讨论】:
-
您没有将
decltype应用于成员名称,而是将其应用于逗号表达式。所以这甚至与 id-expressions 的特殊情况无关。
标签: c++ templates sfinae decltype