C++: Конструктор, принимающий только строковый литерал

Действительно ли возможно создать конструктора (или функциональная подпись, в этом отношении), который только принимает строковый литерал, но не, например. char const *?

Действительно ли возможно иметь две перегрузки, которые могут различать строковые литералы и char const *?

C++ 0x отчасти позволил бы это с пользовательским суффиксом - но я ищу "более раннее" решение.

Объяснение: предотвращение помещает копию в "кучу" строк, которые не будут изменены при предоставлении как строковые литералы.

Эти строки непосредственно переходят к API, ожидая a const char * без любой обработки. Большинство вызовов действительно использует литералы, требующие никакой дополнительной обработки, только в нескольких случаях, они создаются. Я ищу возможность сохранить собственное поведение вызова.

Примечание: - так как это подходит в ответах: рассматриваемый код не использует std::string вообще, но хороший пример был бы:

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; }
}

Результаты:

(1) это не может быть сделано.
(2) Я понял, что даже не ищу литерал, но для постоянного во времени компиляцией (т.е. "что-либо, что не должно быть скопировано").

Я буду, вероятно, использовать следующий шаблон вместо этого:

const literal str_Ophelia = "Ophelia";

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

с простым

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

Это не мешает никому злоупотребить им (я должен найти лучшее имя...), но это позволяет необходимую оптимизацию, но остается безопасным по умолчанию.

20
задан peterchen 11 January 2010 в 16:35
поделиться

4 ответа

Нет, вы просто не можете сделать это - строковые литералы и Const Char * являются взаимозаменяемыми. Один обходной путь может заключаться в том, чтобы представить специальный класс для проведения указателей на строковые литералы и сделать конструктор только принять это. Таким образом, когда вам нужно пройти буквальный, вы называете конструктором этого класса и передайте временный объект. Это не полностью предотвращает неправильное использование, но делает код гораздо более ремонтом.

9
ответ дан 29 November 2019 в 23:23
поделиться

Если вы точно знаете, как вы точно знаете, как ваш компилятор и платформа справится со строчными литералами, можно было бы написать решение Это может сделать это. Если вы знаете, что ваш компилятор всегда ставит строковые литералы в определенную область памяти, вы можете проверить указатель на границах этой памяти. Если он падает в этот блок, у вас есть строковый литерал; В противном случае у вас есть строка, хранящаяся на куче или стеке.

Тем не менее, это решение будет платформенным / компилятором. Это не было бы портативным.

3
ответ дан 29 November 2019 в 23:23
поделиться

Рабочий раствор на основе IDEA IDEAU :

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
}
19
ответ дан 29 November 2019 в 23:23
поделиться

На некоторых платформах мне приходилось объявлять строковые литералы как статический const char *, чтобы программа имела доступ к тексту из Read-Only Memory. При объявлении как const char *, ассемблерный листинг показывал, что текст скопирован из ПЗУ в стековую переменную.

Вместо того, чтобы беспокоиться о приемнике, возможно, попробуйте объявить строковые литералы со статическим const char *.

0
ответ дан 29 November 2019 в 23:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: