简体   繁体   English

如何使用非尾随decltype返回类型定义外联类模板成员函数

[英]How do I define an out-of-line class template member function with a non-trailing decltype return type

template <class T>
struct foo {
    int x;
    decltype(x) f1();
};

It seems to be impossible to define f1 out-of-line. 似乎不可能将f1定义为脱节。 I have tried the following definitions, and none of them work: 我尝试了以下定义,但它们都不起作用:

template <class T> decltype(x) foo<T>::f1() {}
template <class T> auto foo<T>::f1() -> decltype(x) {}
template <class T> auto foo<T>::f1() { return x; }
template <class T> decltype(std::declval<foo<T>>().x) foo<T>::f1() {}
// This return type is copied from the gcc error message
template <class T> decltype (((foo<T>*)(void)0)->foo<T>::x) foo<T>::f1() {}

This isn't a problem in real code because changing the in-class declaration of f1 to auto f1() -> decltype(x); 这在实际代码中不是问题,因为将f1的类内声明更改为auto f1() -> decltype(x); allows the second definition. 允许第二个定义。 but I'm puzzled as to why that changes anything. 但我很困惑为什么会改变什么呢。 Is it even possible to declare the original f1 out-of-line? 是否有可能将原始f1声明为脱离线?

As dumb as this might seem, I believe the following is correct: 尽管看起来很愚蠢,但我相信以下是正确的:

template <class T>
struct foo {
    int x;
    decltype(x) f1();
};

template <class T>
int foo<T>::f1() { return 0; }

Clang accepts it, but GCC doesn't, so I am going to say that I think GCC has a bug. Clang接受了它,但是GCC没有,所以我要说我认为GCC有一个bug。 [ Coliru link ] [ Coliru链接 ]

The issue is whether these two declarations of f1 declare the same function (more technically, the same member function of the same class template). 问题是f1这两个声明是否声明了相同的函数(从技术上讲,同一个类模板的成员函数相同)。 This is governed by [basic.link]/9, according to which: 这由[basic.link] / 9管理,根据其中:

Two names that are the same (Clause 6) and that are declared in different scopes shall denote the same variable, function, type, template or namespace if 两个相同的名称(第6条)和在不同范围内声明的名称应表示相同的变量,函数,类型,模板或名称空间

  • both names have external linkage or else both names have internal linkage and are declared in the same translation unit; 两个名称都有外部链接,否则两个名称都有内部联系,并在同一个翻译单元中声明; and
  • both names refer to members of the same namespace or to members, not by inheritance, of the same class; 两个名称都指向同一名称空间的成员或同一类的成员,而不是继承。 and
  • when both names denote functions, the parameter-type-lists of the functions (11.3.5) are identical; 当两个名称都表示函数时,函数的参数类型列表(11.3.5)是相同的; and
  • when both names denote function templates, the signatures (17.5.6.1) are the same. 当两个名称都表示功能模板时,签名(17.5.6.1)是相同的。

The requirements appear to be satisfied, provided that the return types are in fact the same (since the return type is part of the signature for a class member function template, according to [defns.signature.member.templ]). 只要返回类型实际上是相同的(因为返回类型是类成员函数模板的签名的一部分,根据[defns.signature.member.templ]),似乎满足要求。 Since foo<T>::x is int , they are the same. 由于foo<T>::xint ,它们是相同的。

This would not be the case if the type of x were dependent. 如果x的类型是依赖的,则不会出现这种情况。 For example, GCC and Clang both reject the definition when the declaration of x is changed to typename identity<T>::type x; 例如,当x的声明更改为typename identity<T>::type x;时,GCC和Clang都拒绝该定义typename identity<T>::type x; . [ Coliru link ] In that case, [temp.type]/2 would apply: [ Coliru link ]在这种情况下,[temp.type] / 2适用:

If an expression e is type-dependent (17.6.2.2), decltype( e ) denotes a unique dependent type. 如果表达式e是类型依赖的(17.6.2.2),则decltype( e )表示唯一的依赖类型。 Two such decltype-specifiers refer to the same type only if their expression s are equivalent (17.5.6.1). 只有当它们的表达式 s是等价的(17.5.6.1)时,两个这样的decltype-specifiers才引用相同的类型。 [ Note: However, such a type may be aliased, eg, by a typedef-name . [ 注意:但是,这种类型可能是别名,例如,通过typedef-name end note ] - 结束说明 ]

Perhaps GCC is in error for considering x to be type-dependent (it shouldn't be). 也许GCC错误地认为x是依赖于类型的(它不应该是)。 However, this note suggests a workaround: 但是,本说明提出了一种解决方法:

template <class T>
struct foo {
    int x;
    decltype(x) f1();
    using x_type = decltype(x);
};

template <class T>
typename foo<T>::x_type foo<T>::f1() { return 0; }

This works on both GCC and Clang. 这适用于GCC和Clang。 [ Coliru link ] [ Coliru链接 ]

(I cheated... sort of) (我作弊......有点)

Using MSVC I clicked on "quick action -> create function declaration" for that member function and got this: 使用MSVC我点击了该成员函数的“快速操作 - >创建函数声明”并获得了:

template<class T>
decltype(x) foo<T>::f1()
{
    return x;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用decltype尾随返回类型来专门化功能模板 - Specialize function template with decltype trailing return type 是否可以使用decltype来确定前向声明的模板类的成员函数的返回类型? - Is it possible to use decltype to figure out the return type of a member function of a forward declared template class? 定义外部成员模板功能 - Defining out-of-line member template functions 如何使用 enable_if 为模板 class 成员进行外联定义 - How to use enable_if for out-of-line definition for a template class member decltype作为类成员函数中的返回类型 - decltype as a return type in class member function 合法使用非尾随功能模板参数包? - Legal use of non-trailing function template parameter pack? 使用带有可变参数模板函数的 decltype 的尾随返回类型 - trailing return type using decltype with a variadic template function 如何使用模板参数编写外部构造函数? - How do you write out-of-line constructor with template parameters? 离线可变参数模板功能 - Out-of-line variadic template function 在另一个成员函数的尾随返回类型中获得推断成员函数的decltype是否格式良好? - Is getting the decltype of a deduced member function inside the trailing return type of another member function well-formed?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM