Search code examples
c++c++14language-lawyerstdatomicaggregate-initialization

Initialize atomic members in aggregate


There seems no way to initialize atomic members in aggregate using C++14. The following doesn't work (live on gcc 8.0.1):

#include <atomic>
#include <iostream>

struct stru {
  std::atomic_int32_t val_0;
  std::atomic_int32_t val_1;
};

int main() {
  auto p = new stru{0, 1};
  std::cout << p->val_0 << ", " << p->val_1 << std::endl; 
}

The error message:

error: use of deleted function 'std::atomic<int>::atomic(const std::atomic<int>&)'
   auto p = new stru{0, 1};
                     ^

This is because atomic types are neither copyable nor movable, and is thus not copy-initializable. The following seems to work however (live on gcc 8.0.1).

#include <atomic>
#include <iostream>

struct stru {
  std::atomic_int32_t val_0;
  std::atomic_int32_t val_1;
};

int main() {
  auto p = new stru{};
  std::cout << p->val_0 << ", " << p->val_1 << std::endl; 
}

This effectively performs zero initialization, and is thus unable to initialize to values other than zero. Is there any way to initialize to other specified values?


Solution

  • Patrick's solution works, but his explanation doesn't look right to me. So I post the explanation I find here. For the code auto p = new stru{{0}, {1}}; aggregate initialization kicks in with the effect:

    If the initializer clause is a nested braced-init-list (which is not an expression), the corresponding array element/class member/public base (since C++17) is list-initialized from that clause: aggregate initialization is recursive.

    As a result, instead of copy initialization, the members are copy list-initialized from the braced-init-list.