1

Is there a standard way to get the 0 and the 1 of a numeric type in C++. This is useful when writing linear algebra routines templated with types that could be: int, double, unsigned int, ...

I am thinking of

static_cast<T>(0)

but I am wondering if there is not a better way.

Niall
  • 30,036
  • 10
  • 99
  • 142
InsideLoop
  • 6,063
  • 2
  • 28
  • 55

4 Answers4

3

Usually just 0 and 1 will be fine, letting the promotion rules do the right thing.

If you want to be sure that they're converted to the expected type, use T(0) and T(1).

(As other answers point out, you could get the zero value from value-intialisation, T() or T{}. But there's no similar way to get 1; and in my view, little point in (slightly) reducing the clarity just to save a single character.)

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
1

In C++11 I prefer using T {}. The nice thing is that it works correctly for any default-constructible type.

5gon12eder
  • 24,280
  • 5
  • 45
  • 92
  • The problem is that things like std::array are not initialized to 0 with the default constructor. Therefore T {}; would be anything but 0. I prefer to get a error message if I consider those types. – InsideLoop Sep 12 '14 at 11:51
  • The default constructor should initialize an object to whatever is an appropriate definition for “empty” for the given type. If your template cannot handle non-numeric types, you could use `std::enable_if` to enforce this. – 5gon12eder Sep 12 '14 at 11:54
  • 2
    @InsideLoop: Being an aggregate, `std::array` is zero-initialised if you use `{}` or `()` to specify value-initialisation. (And even if that weren't the case, what has it got to do with numeric types?) – Mike Seymour Sep 12 '14 at 11:55
  • Mike Seymour: std::array is not per say a numeric type. But you could easily define + and * on these types so that it becomes a Ring (mathematic term) and therefore, you can do linear algebra with it. So for "Mathematicians" it could be considered as a "numeric type". – InsideLoop Sep 12 '14 at 11:58
  • 1
    @InsideLoop: Fair enough. But in any case, value-initialisation with `{}` or `()` **does** zero-initialise all the elements of the array. – Mike Seymour Sep 12 '14 at 12:03
1

Native data types initialized to a default value are initialized to zero.

int a = int(); // 0
double b = double(); // 0.0
T x = T(); // same as static_cast<T>(0) for T as a native type
Community
  • 1
  • 1
vz0
  • 32,345
  • 7
  • 44
  • 77
0

I would use (T)0 what is basically what you already use. If you implement anything near to a linear algebra system, you could consider wrapping all kinds of desired numerical typed in a consistens base class, permitting a more structual representation of fields, rings and the like.

Codor
  • 17,447
  • 9
  • 29
  • 56
  • 2
    C-style cast is something you should NEVER use. – Melkon Sep 12 '14 at 11:48
  • 1
    @Melkon: Why not? It's dangerous if pointer or reference types are involved (where you might end up with an unwanted `const/reinterpret_cast` giving an invalid result instead of a friendly compile-time error), but the question is about numeric conversions. – Mike Seymour Sep 12 '14 at 11:51
  • So you say, you want to avoid const and reinterpret cast. Well, in that case you obviously want to avoid dynamic_cast also, because it's expensive, and it can be a nullptr. So actually you want to use static_cast. Why don't you just write it? – Melkon Sep 12 '14 at 12:07
  • @Melkon: I don't get your point; why should I avoid a C-style cast? – Codor Sep 12 '14 at 12:10
  • Because C-style cast mean, you have no idea what you are doing. You can't be sure, that you will get the result what you expect, in a lot of cases it's a timing bomb. Like you refactor some earlier code, and a static_cast magically become a reinterpret_cast without any notification. It's hard to read, because the reader won't know what happen. C++ have 4 type of cast for a good reason. – Melkon Sep 12 '14 at 12:18
  • @Melkon Thanks for your remark; I will check in more detail. – Codor Sep 12 '14 at 12:32
  • @Melkon: As I said, you want to avoid unwanted `const/reinterpret_cast` **when converting pointer or reference types**, as they can give an invalid result. When converting numeric values, which can't give invalid result, there's no particular reason to avoid the less verbose casts. (I've no idea why you mentioned `dynamic_cast`, that's got nothing to do with numeric conversions or C-style casts.) – Mike Seymour Sep 12 '14 at 13:07