Interface design: security of an overloaded function receiving a string and char array

Say we have a class that can write material for output

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

I was fine with that, its flexible and all that, until I realized

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

This is a really nasty mistake.

We can change some patterns a little.

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"); }
    //...
};

But this method has its problems

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

What should I do? What is the best design?

And before anyone asks, overloading const char (&)[N] doesn't work . It might be possible to create a wrapper for this, but it seems ... overkill?

EDIT Adding a method write(char*)and emitting an error is not ideal. When walking bufaround functions and all of this, it can become const char*.

+6
1

ICS (Implicit Conversion Sequences) ++ , , ..

, vs const char* fiasco, delete .

:

#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 


, " ". , ICS () ""

+5

Source: https://habr.com/ru/post/1017052/


All Articles