Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Constructor accepting only a string literal

Tags:

Is it possible to create a constructor (or function signature, for that matter) that only accepts a string literal, but not an e.g. char const *?

Is it possible to have two overloads that can distinguish between string literals and char const *?

C++ 0x would kind-of allow this with a custom suffix - but I'm looking for an "earlier" solution.

Rationale: avoiding heap copy of strings that won't be modified when given as string literals.

These strings directly go to an API expecting a const char * without any processing. Most calls do use literals requiring no additional processing, only in a few cases they are constructed. I am looking for a possibility to preserve the native call behavior.

Note: - since it comes up in the answers: the code in question does not use std::string at all, but a good example would be:

class foo
{
   std::string m_str;
   char const * m_cstr;      
 public:
   foo(<string literal> s) : m_cstr(p) {}
   foo(char const * s) : m_str(s) { m_cstr = s.c_str(); }
   foo(std::string const & s) : m_str(s) { m_cstr = s.c_str(); }

   operator char const *() const { return m_cstr; }
}

Results:

(1) it can't be done.
(2) I realized I am not even looking for a literal, but for a compile-time-constant (i.e. "anything that needs not be copied").

I will probably use the following pattern instead:

const literal str_Ophelia = "Ophelia";

void Foo()
{
  Hamlet(str_Ophelia, ...);  // can receive literal or string or const char *
}

with a simple

struct literal  
{ 
   char const * data; 
   literal(char const * p) : data(p) {} 
   operator const char *() const { return data; }
};

That doesn't stop anyone from abusing it (I should find a better name...), but it allows the required optimization but remains safe by default.

like image 253
peterchen Avatar asked Jan 11 '10 11:01

peterchen


People also ask

Why are C string literals read-only?

The string literal is stored in the read-only part of memory by most of the compilers. The C and C++ standards say that string literals have static storage duration, any attempt at modifying them gives undefined behavior. s is just a pointer and like any other pointer stores address of string literal.

Is string literal in C?

A "string literal" is a sequence of characters from the source character set enclosed in double quotation marks (" "). String literals are used to represent a sequence of characters which, taken together, form a null-terminated string.

Can string literal be modified in C?

C Language Undefined behavior Modify string literalAttempting to modify the string literal has undefined behavior. However, modifying a mutable array of char directly, or through a pointer is naturally not undefined behavior, even if its initializer is a literal string.


1 Answers

Working solution based on sbi idea:

struct char_wrapper
{
    char_wrapper(const char* val) : val(val) {};
    const char* val;
};

class MyClass {
public:
  template< std::size_t N >
  explicit MyClass(const char (&str)[N])
  {
      cout << "LITERAL" << endl;
  }
  template< std::size_t N >
  explicit MyClass(char (&str)[N])
  {
      cout << "pointer" << endl;
  }    
  MyClass(char_wrapper m)
  {
     cout << "pointer" << endl;
  }
};

int main()
{
    MyClass z("TEST1");     // LITERAL
    const char* b = "fff";
    MyClass a(b);           // pointer
    char tmp[256]; 
    strcpy(tmp, "hello"); 
    MyClass c(tmp);         // pointer
}
like image 101
Kirill V. Lyadvinsky Avatar answered Nov 01 '22 15:11

Kirill V. Lyadvinsky