Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interface design: safety of overloaded function taking string and char array

Tags:

c++

interface

Say we have a class that can write stuff to output

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

I was fine with this, 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!

That is a really nasty bug.

We can amend somewhat with some templating

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 do I do? What is a better design?

And before anyone asks, overloading for const char (&)[N] does not work. It might be feasible to create a wrapper to do this, but that seems... overkill?

EDIT Adding a method write(char*) and emitting an error there is not ideal. When passing buf around through functions and all that, it might become const char*.

like image 558
Passer By Avatar asked May 06 '17 11:05

Passer By


People also ask

Which of the following is are correct for an overloaded method or a function in oops?

In function overloading function has same name but accessing depends on the no. And type of arguments so, answer is option A & B. Overloading is nothing but same function with different arguments.

Which of the following can be used in place of overloading?

The correct answer is option4. Key Points Both functions and operators can be overloaded. C++ allows you to specify more than one definition for a function name or an operator in the same scope, which is called function overloading and operator overloading respectively. Hence the correct answer is function.

What is method overloading in C++?

C++ lets you specify more than one function of the same name in the same scope. These functions are called overloaded functions, or overloads. Overloaded functions enable you to supply different semantics for a function, depending on the types and number of its arguments.

What is operator overloading in Java?

Operator overloading is a technique by which operators used in a programming language are implemented in user-defined types with customized logic that is based on the types of arguments passed.


1 Answers

ICS (Implicit Conversion Sequences) during overload resolution in C++ can produce surprising results as you've noticed, and also quite annoying..

You can provide necessary interfaces you need, then carefully employ templates to handle the string literal vs const char* fiasco by taking advantage of partial ordering to delete the unwanted overload.

Code:

#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]);
}

Prints:

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

Demo


Note that the solution above inherits a disadvantage of "overloading a function with an unconstrained Forwarding Reference". This means that all ICS to the argument type(s) of the viable functions in the overload set will be "deleted"

like image 197
WhiZTiM Avatar answered Oct 03 '22 15:10

WhiZTiM