Избегайте двойного вызова функции при назначении строки в списке инициализатора ctor

В следующем примере кода я хочу инициализировать std::string A::str_ в Aсписок инициализатора с возвращаемым значением из функции (которая может возвращать NULL) или const char*, Но мне не нравится тот факт, что Func() называется дважды.

#include <iostream>

const char* Func()
{
  char* p = NULL;
  // Assign p: may be NULL or non-NULL
  return p;
}

class A
{
public:
  A() : str_( Func() ? Func() : "NULL" ) {}

  std::string str_;
};

int main( int argc, char* argv[] )
{
  A a;
  std::cout << a.str_ << std::endl;
  return 0;
}

Я хотел бы сделать что-то вроде этого:

A() : str_( ( const char*& tmp = Func() ) ? tmp : "NULL" ) {}

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

Существует ли синтаксис C++03, который позволил бы инициализировать A::str_ в списке инициализатора, вызывая Func() только один раз, и без использования глобальных / статических переменных? Если есть решение, которое использует временные переменные, я хотел бы изучить его синтаксис.

2 ответа

Решение

В C++11 используйте конструктор делегата

class A
{
private:
    A(const char* s) str_(s ? s : "NULL") {}
public:
  A() : A(Func()) {}

  std::string str_;
};

В C++03 создайте помощник функции

class A
{
private:
    static const char* FuncNotNull() { const char* s = Func(); return s ? s : "NULL"); }
public:
  A() : str_(FuncNotNull()) {}

  std::string str_;
};

Вот решение, в котором лямбда-выражение "злоупотребляют":

A() : str_( ([]()->const char*{ const char* p=Func(); return (p ? p : "NULL"); })() ) {}

Я на самом деле проголосовал за ответ Джарода. Но я нахожу лямбда-штуку такой уродливой, что я тоже хотел это показать:-)

Другие вопросы по тегам