通过引用或值捕获句柄到类模板ctor

Posted

技术标签:

【中文标题】通过引用或值捕获句柄到类模板ctor【英文标题】:Capture handle by reference or by value to class template ctor 【发布时间】:2020-07-14 21:06:17 【问题描述】:

考虑一个模板类InputBuffer

template<class Source, size_t Capacity>
class InputBuffer

    public:
        explicit InputBuffer(Source src);

        int getchar();

    private:
        std::byte const* m_read_ptr;
        std::byte const* m_last_valid;
        Source m_src;
        std::array<std::byte, Capacity> m_data;

        void fetchAndResetPointers();
;

问题:构造函数是否应该接受src 作为引用并存储指针而不是按值获取? 非常调用者在这里期望引用语义。但是,也有可能Source 已经是某种指针,然后,通过引用获取src 并存储指针会导致不必要的间接。如果不通过引用传递,用户可以根据需要使用std::ref

【问题讨论】:

【参考方案1】:

在我看来,这个类并不好 - 你假设“源”需要 m_read_ptrm_last_validm_data 作为上下文。但是,如果它是一个文件,例如,它不需要这些。相反,将此类重写为接口,或者更好的是,根本不创建泛型类并在处理“源”时使用模板,例如伪代码:

class FileBuffer 
public:
  explicit FileBuffer(File* f) : m_f(f) 
  int getchar()  return read(f, 1); 
private:
  File* m_f;
;

template<class T>
void print_from_buffer_to_stdout(T& buf) 
  std:: cout << buf.getchar();


int main() 
  FileBuffer f = get_file_buffer(); // somehow
  print_from_buffer_to_stdout(f);

【讨论】:

其实m_read_ptr会指向本地缓冲区数组,fetchAndResetPointers会在buffer为空时调用(m_read_ptr == m_last_valid)。您的建议不是缓冲区:它依赖于 File 在内部提供缓冲区。使用 InputBuffer 的原因是调用 read 可能会产生很大的开销,因此您通常调用 read 来获取多个字节,例如一整页。 你没有抓住重点——“inputbuffer”类不应该包含“Source”作为其成员,或者不包含所有其他成员/方法。 抱歉,您确实需要了解如何实现缓冲 I/O。输入缓冲区的实现至少需要知道它的来源,如果它不是 getchar 的参数的话。但它不能作为 getchar 的参数,因为这会引入不一致。

以上是关于通过引用或值捕获句柄到类模板ctor的主要内容,如果未能解决你的问题,请参考以下文章

将 lambda 作为参数传递 - 通过引用或值?

未捕获的引用错误:应用引导模板后未定义 $

类(或结构)通过模板自引用

类(或结构)通过模板自引用

通过引用或值传递对象

std::any 用于仅移动模板,其中 copy-ctor 内的 static_assert 等于编译错误,但为啥呢?