Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Coding style conformance

...

Code Block
bgColor#FFCCCC
langcpp
#include <initializer_list>
#include <iostream>

class C {
  std::initializer_list<int> Ll;
  
public:
  C() : Ll{1, 2, 3} {}
  
  int first() const { return *Ll.begin(); }
};

void f() {
  C c;
  std::cout << c.first();
}

...

Code Block
bgColor#ccccff
langcpp
#include <initializer_list>
#include <iostream>
#include <vector>
 
class C {
  std::vector<int> Ll;
  
public:
  C() : Ll{1, 2, 3} {}
  
  int first() const { return *Ll.begin(); }
};
 
void f() {
  C c;
  std::cout << c.first();
}

...

Code Block
bgColor#FFcccc
langcpp
class S {
  int Vv;
public:
  S() : Vv(12) {} // Not a trivial constructor
  void f();
};
 
void f() {
  // ...
 
  goto bad_idea;
 
  // ...
  S s; // Control passes over the declaration, so initialization does not take place.
 
bad_idea:
  s.f();
}

...

Code Block
bgColor#ccccff
langcpp
class S {
  int Vv;
public:
  S() : Vv(12) {} // Not a trivial constructor
  void f();
};
 
void f() {
  S s;

  // ...

  goto bad_idea;

  // ...

bad_idea:
  s.f();
}

...

Code Block
bgColor#FFcccc
langcpp
#include <algorithm>
#include <cstddef>
#include <memory>
#include <type_traits>
 
class S {
  int i;

public:
  S() : i(0) {}
  S(int i) : i(i) {}
  S(const S&) = default;
  S& operator=(const S&) = default;
};

template <typename Iter>
void f(Iter Ii, Iter Ee) {
  static_assert(std::is_same<typename std::iterator_traits<Iter>::value_type, S>::value,
                "Expecting iterators over type S");
  ptrdiff_t count = std::distance(Ii, Ee);
  if (!count) {
    return;
  }
  
  // Get some temporary memory.
  auto p = std::get_temporary_buffer<S>(count);
  if (p.second < count) {
    // Handle error; memory wasn't allocated, or insufficient memory was allocated.
    return;
  }
  S *vals = p.first; 
  
  // Copy the values into the memory.
  std::copy(Ii, Ee, vals);
  
  // ...
  
  // Return the temporary memory.
  std::return_temporary_buffer(vals);    
}

...

Code Block
unsigned char *buffer = new (std::nothrow) unsigned char[sizeof(S) * object_count];
S *result = reinterpret_cast<S *>(buffer);
while (Ii != Ee) {
  *result = *Ii; // Undefined behavior
  ++result;
  ++Ii;
}

The act of dereferencing result is undefined behavior because the memory pointed to is not an object of type S within its lifetime.

...

Code Block
bgColor#ccccff
langcpp
#include <algorithm>
#include <cstddef>
#include <memory>
#include <type_traits>
 
class S {
  int i;
public:
  S() : i(0) {}
  S(int i) : i(i) {}
  S(const S&) = default;
  S& operator=(const S&) = default;
};

template <typename Iter>
void f(Iter Ii, Iter Ee) {
  static_assert(std::is_same<typename std::iterator_traits<Iter>::value_type, S>::value,
                "Expecting iterators over type S");
  ptrdiff_t count = std::distance(Ii, Ee);
  if (!count) {
    return;
  }
  
  // Get some temporary memory.
  auto p = std::get_temporary_buffer<S>(count);
  if (p.second < count) {
    // Handle error; memory wasn't allocated, or insufficient memory was allocated.
    return;
  }
  S *vals = p.first; 
  
  // Copy the values into the memory.
  std::uninitialized_copy(Ii, Ee, vals);
  // It is also acceptable to use a raw_storage_iterator in situations where an iterator
  // over uninitialized objects is required.
  //  std::copy(Ii, Ee, std::raw_storage_iterator<S*, S>(vals));
  
  // ...
  
  // Return the temporary memory.
  std::return_temporary_buffer(vals);    
}

...