使用 typealias 代替定义中 class 中定义的 typedef

Using typealias in place of typedef defined in class in definition

为什么编译失败?我正在尝试减少重复次数,因为在实际代码中 class 名称很大,而 type 实际上是一个很长的名称

https://godbolt.org/z/8YarWs

#include <vector>

template<typename T>
struct S {
    using type = std::vector<T>;

    type f() const;
};

template<typename T>
using type_t = typename S<T>::type;

template <typename T>
type_t<T> S<T>::f() const { }

上面的代码失败如下

<source>:17:14: error: no declaration matches 'type_t<T> S<T>::f() const'
   17 | type_t < T > S < T >::f() const
      |              ^~~~~~~
<source>:8:10: note: candidate is: 'S<T>::type S<T>::f() const'
    8 |     type f() const
      |          ^
<source>:4:8: note: 'struct S<T>' defined here
    4 | struct S
      |        ^

这是一个 GCC 错误;最近的(1) 已确认打开的错误报告似乎是:

  • Bug 69348: 别名声明不能在声明符的限定符内使用

这突出表明 GCC 拒绝以下格式正确的程序:

template <class T>
struct X {
    int foo();
};

template <class T>
using foo2 = X<T>;

template <class T>
int foo2<T>::foo()
{
}

带有错误信息

error: invalid use of incomplete type 'struct X<T>'

(1) 扫描 GCC:s bugzilla,似乎有许多与别名模板相关的“拒绝有效”(open/unconfirmed) 错误报告,在大多数报告中 clang 是报告接受(可以说是格式正确的)示例程序。

我不记得确切原因,但我知道这与编译器解析类型名称和符号的顺序有关...
您可以通过稍微更改声明的结构来使其工作。

由于我不知道这对您来说有多大可能,所以我包含了一些变体。

https://godbolt.org/z/bGPGhW

#include <vector>
#include <iostream>

template <typename T>
struct S
{
    using type = std::vector<T>;

    auto f() const -> decltype(type());
    auto g() const -> decltype(type()); 
    decltype(type()) h() const;
};

template <typename T>
using type_t = typename S<T>::type;

template <typename T>
auto S<T>::f() const -> decltype(type())
{
    std::cout << "foo" << std::endl;
    type_t<T> t;
    return t;
}

template <typename T>
using other_type_t = decltype(typename S<T>::type());

template <typename T>
auto S<T>::g() const -> other_type_t<T>
{
    std::cout << "bar" << std::endl;
    other_type_t<T> t;
    return t;
}

template <typename T>
using last_type_t = decltype(typename S<T>::type());

template <typename T>
last_type_t<T> S<T>::h() const
{
    std::cout << "foobar" << std::endl;
    last_type_t<T> t;
    return t;
}

int main(){
    S<int> s;
    auto t = s.f();
    auto r = s.g();
    auto l = s.h();
    return 0;
}

输出:

Program returned: 0
Program stdout

foo
bar
foobar