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

前端之家收集整理的这篇文章主要介绍了c – 如何使用非尾随decltype返回类型定义外联类模板成员函数前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
template <class T>
struct foo {
    int x;
    decltype(x) f1();
};

似乎不可能将f1定义为脱节.我尝试了以下定义,但它们都不起作用:

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() {}

这在实际代码中不是问题,因为将f1的类内声明更改为auto f1() – > decltype(X);允许第二个定义.但我很困惑为什么会改变什么呢.是否有可能将原始f1声明为脱离线?

解决方法

尽管看起来很愚蠢,但我相信以下是正确的:
template <class T>
struct foo {
    int x;
    decltype(x) f1();
};

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

Clang接受了它,但是GCC没有,所以我要说我认为GCC有一个bug. [Coliru link]

问题是f1的这两个声明是否声明了相同的函数(从技术上讲,同一个类模板的成员函数相同).这由[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

  • 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; and
  • when both names denote function templates,the signatures (17.5.6.1) are the same.

只要返回类型实际上是相同的(因为返回类型是类成员函数模板的签名的一部分,根据[defns.signature.member.templ]),似乎满足要求.由于foo< T> :: x是int,它们是相同的.

如果x的类型是依赖的,则不会是这种情况.例如,当x的声明更改为typename identity< T> :: type x;时,GCC和Clang都拒绝该定义. [Coliru link]在这种情况下,[temp.type] / 2将适用:

If an expression e is type-dependent (17.6.2.2),decltype(e) denotes a unique dependent type. Two such
decltype-specifiers refer to the same type only if their expressions are equivalent (17.5.6.1). [ Note: However,such a type may be aliased,e.g.,by a typedef-name. — end note ]

也许GCC错误地认为x是依赖于类型的(它不应该是).但是,本说明提出了一种解决方法

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; }

这适用于GCC和Clang. [Coliru link]

猜你在找的C&C++相关文章