无法获取返回constexpr auto的函数类型
Unable to get type of function returning constexpr auto
我正在尝试在类中使用属性系统。
属性具有相应的成员指针、名称和int(来自enum),用于唯一标识它。
下面是定义属性的代码:template<typename Class, typename T>
struct MemberProperty
{
constexpr MemberProperty(T Class::*aMember, const char* aName, int aId)
: member(aMember), name(aName), id(aId)
{}
T Class::*member;
const char* name;
int id;
};
我通过调用这个函数来创建属性:
template <typename Class, typename T>
constexpr auto makeProperty(T Class::*member, const char* name, int id) {
return MemberProperty<Class, T>{member, name, id};
}
我的目标是为这样的类定义属性:
class User
{
public:
enum PropertiesEnum
{
Property_Name
};
string m_name;
static constexpr auto Properties() {
return std::make_tuple(
makeProperty(&User::m_name, "name", User::Property_Name)
);
}
using PropertiesType = decltype(Properties());
//PropertyManager<PropertiesType> m_propertyManager;
};
我希望能够取消声明m_propertyManager
的行注释。问题是这不能编译。在c++中,我得到:
在Visual Studio 2015中,我得到:错误:在扣除'auto'之前使用'static constexpr auto User::Properties()'
错误C3779: 'User::UserProperties':一个返回'auto'的函数在定义之前不能使用
我怎样才能使它工作?它看起来像一个循环依赖,但我不知道如何使它工作。下面是示例:
http://coliru.stacked-crooked.com/a/24e7f5ea7f83da6f我猜是由于[class.mem]/6。
它声明:
在类说明符的结尾}处,类被认为是完全定义的对象类型([basic.types])(或完整类型)。[…]
注意最后一个语句:
[…否则,在其自身的类成员规范中被认为是不完整的。
别名声明被认为是成员规范的一部分,在
规则的例外中没有提到。[…在类成员规范中,类在函数体、默认参数、异常规范和默认成员初始化器(包括嵌套类中的这些东西)中被认为是完整的。[…]
通过进一步简化你的例子,我们有:
struct S {
auto f() {}
using T = decltype(f());
};
int main() {}
错误是差不多的。
如上所述,在using声明处,类不是完全定义的类型,因此不是它的成员函数。
因此,不能对成员函数的返回类型进行演绎,也不能满足using声明。
注意,要推断返回类型,编译器必须查看函数的定义,也就是函数体。
换句话说,它(在概念上)离这样做并不远:
auto f();
using T = decltype(f());
int main() {}
如何计算尚未定义的函数的返回类型?
你不能,上面的代码确实不起作用。
在这种情况下,成员函数是constexpr
函数这一事实不会改变任何东西。
正如在问题的注释中提到的,您可以通过尾随返回类型显式指定返回类型来解决问题。
在这种情况下,不再需要定义,您可以从声明中获取返回类型。实际上,对于返回类型根本没有任何扣除。
- 为什么在我的函数类型后使用引用运算符 (&) 允许我修改它返回的值?
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 是否有任何建议来统一函数类型限定符并简化可恶的函数类型?
- 关于 C++ 中的函数类型定义
- 用于检测函数类型是否为否的特征
- 函数类型参数的模板参数推导
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- C++无效的函数类型转换
- STL 函数和函数类型与函数指针类型
- 如何将result_of与函数类型定义一起使用
- 将模板(没有规范)传递给 std::thread() 会出现错误:<未解析的重载函数类型>匹配错误
- C++ 编译错误:gnu_printf是无法识别的格式函数类型
- 专门用于"direct"函数类型(与函数指针类型相对)
- 将函数类型作为模板参数传递不会编译
- 通过参数传递 lambda(无函数类型模板)
- 如何在模板参数中分离函数类型返回类型和参数
- 为什么比较函数类型需要指定为模板参数?
- 带有限定符的函数类型定义用例
- 如何声明对函数类型的常量引用
- 非类型模板参数允许各种函数类型?