2

Given a templated C++ function in C++-03:

template <typename data>
void example(data arg) {
  // How to get POD zero initialized and non-POD, default constructor?
  data x();
  ...
}

How can I zero out a templated argument if it is POD (e.g. int gets a 0, float gets a 0.0, etc.) or, for non-POD, use its default constructor?

I see with class members, this is handled as explained here with:

struct X
{
   int x;
};

X x;        //x.x is not initialized
X y = X();  //y.x is 0

But in this situation, the variable is not a member of a class, so how do you correspondingly get this effect of initializing a POD typed variable and default constructing a non-POD typed variable?

Community
  • 1
  • 1
WilliamKF
  • 41,123
  • 68
  • 193
  • 295
  • Are you attempting to clear `arg` (as in `arg = 0;` for some specific types), or attempting to declare a variable of the same type as `arg`, and value-initialising that? If the former, what's `x` doing there? If the latter, what's `arg` doing there? –  Jul 11 '15 at 19:30
  • possible duplicate of [Default initialization of POD types in C++](http://stackoverflow.com/questions/15212261/default-initialization-of-pod-types-in-c) – Captain Giraffe Jul 11 '15 at 19:31
  • @PiotrS. Please post answers as answers, not as comments. It may unnecessarily call the copy constructor, though. Depending on what specifically the OP is after, there are some other options. –  Jul 11 '15 at 19:33
  • @hvd then let's wait for the OP's clarification – Piotr Skotnicki Jul 11 '15 at 19:34
  • @Piotr S You have the correct answer here. Post is as answer :) – Michael A. Jul 11 '15 at 23:35
  • @CaptainGiraffe Oops, code is corrected now to declare a variable of same type as arg and give a zero default for POD and a default constructor for non-POD. – WilliamKF Jul 12 '15 at 15:49
  • I'm curious, any reason why you aren't accept Piotr S's answer? Are you anticipating potentially having uncopyable types, or don't want the overhead? I have a potential solution, but it's not beautiful, so I wanted to see why this didn't work first. – Nir Friedman Jul 12 '15 at 17:57
  • @NirFriedman PiotrS has not created an answer, just a comment thus far, so I cannot accept anything related to that. – WilliamKF Jul 12 '15 at 18:49
  • Sorry, I don't mean to formally "accept" his "answer". I just mean, he offered a solution above in the comments, does that work for you? – Nir Friedman Jul 12 '15 at 18:51
  • @NirFriedman Yes, I'm using `data x = data();` for non-`const` case and also `const T& data = T();` for case where `const` works. It compiles, but I have not confirmed in the debugger that the value is zeroed out as desired. – WilliamKF Jul 12 '15 at 19:34

3 Answers3

2

You can use const T& data = T();. This is guaranteed to avoid copies and such and T will be value-initialized, which is default construction for types that need it or 0 for all other types.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 1
    I'm curious, can anything be done with this if the OP needs to call non-const members on the created type? Would creating a non-const reference by const casting this reference by UB, or defined, since the actual temporary constructed is not const? – Nir Friedman Jul 12 '15 at 16:38
  • @NirFriedman, Yes, I have at least one case where data cannot be const as its value is conditionally updated, but I don't want a possible UMR, hence I need a default initialization. – WilliamKF Jul 12 '15 at 16:58
1

I'm so sorry to even write this solution, but you could do it using boost and type traits to literally have a different code path for each:

template <class T>
void f(typename boost::enable_if<boost::is_pod<T>, int>::type = 0) {
  T t = T();
  g(t);
}

template <class T>
void f(typename boost::disable_if<boost::is_pod<T>, int>::type = 0) {
  T t;
  g(t);
}

template <class T>
void g(const T & t) {
  std::cerr << t.x << std::endl;
}

Maybe you should use the is_trivially_constructible trait instead of is_pod. I know this isn't exactly beautiful, but it should work, and scales fine. I assume the compiler will do something intelligent with performance, but if you are really concerned you can force g (which is where the rest of your function will be implemented) to be always inlined into f.

Nir Friedman
  • 17,108
  • 2
  • 44
  • 72
0
template <typename data>
void example(data arg) 
{
     arg  = 0;
}

For non POD-s

  1. define appropriate copy constructor which set to zero this object
  2. overload "=" operator