const-reference合格的成员函数

Mar*_*tto 15 c++ c++11

参考限定成员函数的stock示例似乎是这样的:

#include <stdio.h>
#include <stdexcept>
#include <string>

// Easy access to literals
using namespace std::literals;

// File wrapper
class File {
  private:
    //  The wrapped file
    FILE *_file;
  public:
    File(const char *name) : 
        _file(fopen(name, "r")) { 
        // unable to open the file?
        if (!_file) throw std::runtime_error{ "Unable to open file: "s + name };
    } 
    ~File() { 
        fclose(_file);
    } 

    //  Convert to the underlying wrapped file
    operator FILE *() & { 
        return _file;
    } 

    // TODO: Member functions for working with the file
};
Run Code Online (Sandbox Code Playgroud)

这很好用.无法直接从未命名的临时检索基础FILE指针.但是,如果我们使铸造操作符也符合const,那么这似乎不再起作用.

不同的编译器只是吞下它而没有抱怨,即使它是一个非常有用的想法.以,例如std :: string :: c_str()成员函数为例.你觉得它应该是引用限定的(因为否则你有一个无效的指针)但它不是.

这是C++ 11标准中的一个漏洞吗?我在这里错过了什么吗?

Die*_*ühl 16

临时可以绑定到const&限定对象,并且ref-qualifier有效地限定隐式传递的对象(*this).如果要阻止对临时= delete值的调用但允许左值,则可以使用右值引用重载并实现左值版本.const对两个运算符使用限定的引用限定符只需要一个实现和一个= deleted实现:

class File {
    // ...
    FILE* _file;
public:
    operator FILE*() const&& = delete;
    operator FILE*() const& { return this->_file; }
    // ...
};
Run Code Online (Sandbox Code Playgroud)

净效应是您只能将转换用于左值的对象:

int main() {
    File       f;
    File const cf{};

    FILE* fp = f;              // OK
    FILE* cfp = cf;            // OK
    FILE* tfp = File();        // ERROR: conversion is deleted
    FILE* mfp = std::move(cf); // ERROR: conversion is deleted  
}
Run Code Online (Sandbox Code Playgroud)

  • 您可以使用`const && = delete`而不是`&& = delete`,否则const rvalue将绑定到`const&'重载 (7认同)