Можно ли инициализировать переменную с помощью лямбды (при удалении копии ctor)? - PullRequest
4 голосов
/ 29 марта 2019

У меня есть следующий код:

struct A {//<-- Third party library class
  A(){};
  A(const A&) = delete;
  void init(){};
  int i;
};


int f(){
  static A a = []{
    A res; 
    res.init(); 
    return res;
    }();
  return a.i;
}

посмотреть вживую: http://coliru.stacked -crooked.com / a / a5c5912bd79053c3

А при компиляции выдает следующую ошибку:

g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out

main.cpp: In lambda function:

main.cpp:12:12: error: use of deleted function 'A::A(const A&)'

     return res;

            ^~~

main.cpp:4:3: note: declared here

   A(const A&) = delete;

   ^

Я знаю, что мог бы обернуть это в другой struct и инициализировать в этом конструкторе , но это только кажется несколько утомительным. Используя , есть ли у нас «аккуратный» способ обойти эту «проблему»?

Любое решение должно работать одинаково хорошо для статической переменной в функции

Ответы [ 2 ]

4 голосов
/ 29 марта 2019

Если ваш класс не является подвижным, а конструктор копирования удален / недоступен, то у вас нет другого выбора, кроме как вернуть ссылку на статический объект или вернуть указатель. Это потому, что гарантированная копия C ++ 17 elision работает только с prvalues. Поскольку у объекта есть имя в лямбде, его необходимо переместить или скопировать в возвращаемый объект, даже если применяется NRVO.

Вы можете использовать

A& a = []() -> A& {
    static A res; 
    res.init(); 
    return res;
}();

или

auto a = []{
    auto res = std::make_unique<A>(); 
    res->init(); 
    return res;
}();
0 голосов
/ 29 марта 2019

Вы можете вызвать init в конструкторе по умолчанию.Затем вы можете использовать это для статических функций и статических функций-членов.Также можно использовать elision copy для prvalues ​​и предоставлять что-то вроде A res = []{ return A(); }();.

#include <iostream>

struct A {//Third party library class
  constexpr A() :i{}
  { init(); };
  A(const A&) = delete;
  constexpr void init(){ i = 5; };
  int i;
};

struct A_User {
    static constexpr void A_print() {
        constexpr A res{};
        static_assert(res.i == 5);
    }
};

A& static_func() {
    static A res{};
    std::cout << "res static: " << res.i << "\n";
    return res;
}

A res = []{ return A(); /* copy elided since this is prvalue */ }();

int main() {
    std::cout << "res global: " << res.i << "\n";
    auto& static_A = static_func();
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...