c++ - 接口(interface)设计: safety of overloaded function taking string and char array

标签 c++ interface

假设我们有一个类可以写入输出内容

class Writer
{
public:
    int write(const std::string& str);
    int write(const char* str, int len);
    //...
};

我对这个、它的灵 active 以及所有这些都很好,直到我意识到

char* buf = new char[n]; //not terminated with '\0'
//load up buf
Writer w;
w.write(buf);  //compiles!

那是一个真的讨厌的错误。

我们可以通过一些模板进行一些修改

class WriterV2
{
public:
    int write(const std::string& str);
    int write(const char* str, int len);
    template<typename... Args>
    int write(const char*, Args...)
    { static_assert(sizeof...(Args) < 0, "Incorrect arguments"); }
    //...
};

但是这个方法有它的问题

WriterV2 w;
w.write("The templating genius!"); //compile error

我该怎么办?什么是更好的设计?

在任何人询问之前,重载 const char (&)[N] does not work .创建一个包装器来执行此操作可能是可行的,但这似乎...有点矫枉过正?

编辑 添加一个方法 write(char*) 并在那里发出错误并不理想。当通过函数传递 buf 时,它可能会变成 const char*

最佳答案

ICS (Implicit Conversion Sequences)正如您所注意到的,在 C++ 中的重载解析过程中会产生令人惊讶的结果,而且也很烦人..

您可以提供所需的必要接口(interface),然后通过利用 partial ordering 谨慎地使用模板来处理 string literal vs const char* 惨败删除不需要的重载。

代码:

#include <iostream>
#include <string>
#include <type_traits>

class Writer
{
public:
    int write(std::string&&) { std::cout << "int write(std::string)\n"; return 0; }
    int write(const std::string&) { std::cout << "int write(const std::string& str)\n"; return 0; }
    int write(const char*, int){ std::cout << "int write(const char* str, int len)\n"; return 0; }

    template<std::size_t N = 0, typename = std::enable_if_t<(N > 0)> >
    int write(const char (&)[N]) { std::cout << "int write(string-literal) " << N << " \n"; return 0; }


    template<typename T>
    int write(T&&) = delete;

};

int main(){
    char* buf = new char[30];
    const char* cbuf = buf;
    Writer w;

    //w.write(buf);                     //Fails! 
    //w.write(cbuf);                    //Fails! 
    w.write(buf, 30);                   //Ok!    int write(const char*, int);
    w.write(std::string("Haha"));       //Ok!    int write(std::string&&);
    w.write("This is cool");            //Ok!    int write(const char (&)[13]);
}

打印:

int write(const char* str, int len)
int write(std::string)
int write(string-literal) 13 

Demo


请注意,上述解决方案继承了“使用不受约束的转发引用 重载函数”的缺点。这意味着重载集中可行函数的参数类型的所有 ICS 都将被“删除”

关于c++ - 接口(interface)设计: safety of overloaded function taking string and char array,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43819900/

相关文章:

c++ - 为什么即使在调用参数化构造函数时也会调用默认构造函数?

c++ - 使用 OpenGL 的图像幻灯片

java - java或c++中的邻接矩阵来查找连接的节点

java - 集合使用泛型类型转换问题实现和接口(interface)

c# - 是否应该在接口(interface)中声明所有公共(public)方法?

rust - 为什么这个特征 `impl` 被认为泄漏了私有(private)特征?

c++ - 为 std 算法函数创建一个包装器以采用容器而不是迭代器

c++ - ppl,如何正确使用它?

c++ - 高级 iOS GUI(最好使用 C++)

Android Fragments 基础知识 : why? 这在概念上是错误的吗?