【问题标题】:Use of 'static auto&' function before deduction of 'auto'在扣除 'auto' 之前使用 'static auto&' 函数
【发布时间】:2021-06-29 15:55:13
【问题描述】:

有一个分配器:

template<typename T>
class pool_allocator {
public:
    using value_type = T;
    using pointer = value_type *;

    /* Default constructor */
    constexpr pool_allocator( void ) noexcept = default;

    /* Converting constructor used for rebinding */
    template<typename U>
    constexpr pool_allocator( const pool_allocator<U> & ) noexcept {}

    [[nodiscard]] pointer allocate( size_t n, [[maybe_unused]] const pointer hint = nullptr ) const noexcept {
        return get_pool().allocate( n );
    }

    void deallocate( pointer ptr, size_t n ) const noexcept {
        get_pool().deallocate( ptr, n );
    }

private:
    /* Must be defined in particular .cpp files */
    static auto & get_pool( void ) noexcept;
};

它需要为 .cpp 文件中的特定类型定义 get_pool()pool_allocator 在内存池中分配实例。

struct cpu { ... };

要定义池本身 - 实例所在的内存区域可能如下所示:

memory_pool<cpu, 4> cpu_storage;

template<>
auto & pool_allocator<cpu>::get_pool( void ) noexcept {
    return cpu_storage;
}

在尝试使用时:

class process {
    unique_ptr<cpu> m_cpu { nullptr };
};

我面临 GCC 报告的问题:

error: use of 'static auto& ReVolta::pool_allocator<T>::get_pool() [with T = cpu]' before deduction of 'auto'
get_pool().deallocate( ptr, n ); // line of code within the pool_allocator<T>::deallocate(...) implemnetation 

我可以请求帮助吗?

【问题讨论】:

  • 你的get_pool( void)函数声明不应该使用auto作为返回类型,你需要明确指定它的返回类型。
  • get_pool成为免费功能怎么样?
  • @Ranoiaetep 使 get_pool() 免费函数有什么好处?

标签: c++ auto return-type-deduction


【解决方案1】:

我怀疑您要么在单独的 c++ 文件中定义(即提供其主体)并使用了 get_pool 函数,要么它们在同一个文件中但首先使用。

在第一种情况下,您可能会执行以下操作:

// f.hpp
auto f();

// f.cpp
auto f() { return 42; }

// main.cpp
#include "f.hpp"
int main() { return f(); }

现在像试图编译main.cpp 的编译器一样思考。由于您是 c++ 编译器,you can only see the content of f.hpp and main.cpp。但是你怎么知道f的确切返回类型呢?

在第二种情况下,您可能已经做了类似的事情(在单个 cpp 文件中):

auto f();

int main() {
    return f();
}

auto f() {
    return 42;
}

当您编写return f(); 时,编译器仍然需要知道42 的返回类型。但它还没有看到定义。但是,如果您颠倒顺序:

auto f();

auto f() {
    return 42;
}

int main() {
    return f();
}

它会编译。


无论哪种方式,在模板中声明一个函数但不立即跟上定义(与类定义内联或紧跟在标头中的类定义之后)仍然是非常规的,因为如果您定义cpp 文件中的模板成员,you would not be able to use it in other cpp files

【讨论】:

  • 使用这种可能非常规方式的主要动机是拥有一个单一的源 emty(无成员变量)分配器,并且可以选择为特定类型定义各种内存池。例如,pool_allocator&lt;cpu&gt; 应在 memory_pool 内分配,对于其他类型 sample 应使用 memory_pool 等。问题是,池的大小仅在池本身中可用,并且分配器不知道(很高兴知道如何使其对分配器可用,可能会解决问题)
  • @MartinKopecký 原则上你可以使用类似于en.cppreference.com/w/cpp/memory/allocator_traits
  • 你到底是什么意思?我不清楚应该如何使用 allocator_traits 的哪个原则?
猜你喜欢
  • 1970-01-01
  • 2017-09-16
  • 2020-11-24
  • 1970-01-01
  • 1970-01-01
  • 2014-01-12
  • 1970-01-01
  • 2011-12-04
  • 1970-01-01
相关资源
最近更新 更多