4

Consider the following class:

class A {
    const int arr[2];
public:
      A() { }
};

Is it possible to initialize arr from the constructor initializer list or in any other way than on the line where it is declared (i.e. const int arr[2] = {1,2};)?

Note that I'm interested in methods that work with C++98!

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
Szabolcs
  • 24,728
  • 9
  • 85
  • 174
  • 2
    It's started! Explicit non-C++11-ness in questions. (Nothing wrong with that) – Lightness Races in Orbit Nov 17 '11 at 17:59
  • This is a famous deficiency of C++98, which is why we now have C++11! – Kerrek SB Nov 17 '11 at 17:59
  • @TomalakGeret'kal: Great! Now let's rename `C++` to `C++98/03` and migrate all those tags :-) – Kerrek SB Nov 17 '11 at 18:00
  • 5
    Whats this silliness? Please make this tag be c++03 ... or do we want a cc++ tag or maybe a c#java tag? – Johannes Schaub - litb Nov 17 '11 at 18:06
  • 2
    @JohannesSchaub-litb: I didn't realize there was no slash :-( Please feel free to modify/fix/delete as you see fit. `C++-obsolete` might be the most universal name. – Kerrek SB Nov 17 '11 at 18:10
  • 2
    I've changed the C++-9803 tag to c++98, as that's the specific version that was requested. I support having c++98, c++03 etc tags, but lumping every old version together into one tag is brokenness waiting to happen. What happens when C++2x comes out, and c++-obsolete now *includes* c++11? – cHao Nov 17 '11 at 18:29
  • [Well covered in the FAQ.](http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c/4984228#4984228) – Lightness Races in Orbit Nov 17 '11 at 18:35
  • C++03 was just a technical correction of C++098, the Technical Corrigendum 1 (or TC1 for short). Apart from value initialization it introduced nothing new. So talking about that standard, C++98 is a good designator, in my humble opinion. – Cheers and hth. - Alf Nov 17 '11 at 19:03
  • @Alf : Well, value-initialization seems closely tied to this question to me, so the distinction in this case may still be warranted. – ildjarn Nov 17 '11 at 19:05
  • @Alf C++03 is not a TC, but is a new version. Initially they wanted it to be a TC, but eventually it didn't become one. – Johannes Schaub - litb Nov 17 '11 at 20:56
  • @Alf & everyone else: actually I just meant *not* C++11, since that doesn't yet have very good compiler support (in the compilers installed on the servers where I can run my simulation: I'm not free to choose my compiler version). – Szabolcs Nov 17 '11 at 21:02
  • @Johannes: C++03 is sold as the C++ standard "incorporating TC1". In its own words it is a "technically revised" edition of C++98. It was not a separate version: nothing new (except value initialization, which is debatable as to newness) was introduced. In contrast, C++11 is a new version. Lots of new things have been introduced, presumably some things have been deprecated, and at least one earlier deprecated thing (implicit conversion of literal to pointer to non-const) has been removed. Cheers & hth., – Cheers and hth. - Alf Nov 18 '11 at 03:40

3 Answers3

4

By wrapping them in a struct, e.g.:

class A
{
    struct Data
    {
        int arr[2];
    };

    Data const arr;
public:
    A() : arr( someOtherStruct ) {}
};

This does mean that to access the data, you'd have to write arr.arr. It's possible to avoid that by inheriting from the struct:

struct PrivateDataForA
{
    int arr[2];
};

class A : private PrivateDataForA
{
public:
    A() : PrivateDataForA( someOtherStruct ) {}
};

This does make the name of the struct visible outside of the class (which might be an advantage—client code could pass you one as an argument).

If you don't have an instance of the struct handy, say because you want to fill it with values calculated from arguments to the constructor, you can use a static member function:

class A : private PrivateDataForA
{
    static PrivateDataForA createInitializer( int a, int b );
public:
    A( int a, int b ) : PrivateDataForA( createInitializer( a, b ) )
    {
    }
};

For the OP’s concrete example:

#include <iostream>
#include <stddef.h>

typedef ptrdiff_t   Size;
typedef Size        Index;

template< class Element, Size n >
struct Array{ Element elem[n]; };

class A {
    Array<int, 2> const arr_;       // const int arr[2];

    A& operator=( A const& );       // No such.

    static Array<int, 2> const& oneAndTwo()
    {
        static Array<int, 2> const a = {1, 2};
        return a;
    }

public:
    A(): arr_( oneAndTwo() ) {}
    int at( Index i ) const { return arr_.elem[i]; }
};


int main()
{
    using namespace std;

    A o;
    for( int i = 0;  i < 2;  ++i )
    {
        cout << o.at( i ) << endl;
    }
}
Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Essentially you're advocating use of `boost::array<>`/`std::tr1::array<>` -- why not say that directly? – ildjarn Nov 17 '11 at 20:25
  • @ildjarn Because I wasn't. I'm not actually that familiar with either of those classes, and wrapping data in a `struct` is a useful technique to know in general (although only really necessary when C-style arrays are being used). – James Kanze Nov 18 '11 at 08:40
  • Well given that `std::array<>` is now _standard_, it's a good thing to be familiar with. ;-] (And again, it's exactly what your answer is describing.) – ildjarn Nov 18 '11 at 16:01
2

Initializing array elements to non-zero values requires C++11 support.

In C++03, it's only possible to value-initialize your array, resulting in each element's value being 0:

class A {
    const int arr[2];
public:
    A() : arr() { }
};

For the relevant C++03 standardese, see this question and answer:
How can i use member initialization list to initialize it?

(I'm going to assume that by C++98 you mean not C++11, i.e. that C++03 is acceptable. If this assumption is wrong, please say so.)

Community
  • 1
  • 1
ildjarn
  • 62,044
  • 9
  • 127
  • 211
  • -1: OP specifically gave non-zero values as an example, and non-C++11 as a requirement. – Lightness Races in Orbit Nov 17 '11 at 18:32
  • @Tomalak : I mentioned the only thing that _is_ possible to do, which obviously also indicates what _isn't_ possible to do (everything that wasn't mentioned). Don't be petty. And to be clear, the concrete question is "*Is it possible to initialize `arr` from the constructor initializer list or in any other way than on the line where it is declared?*" OP's example aside, I directly answer that question. – ildjarn Nov 17 '11 at 18:33
  • Don't call me petty. If the OP used non-zero element values as his example, it's pretty clear that that's what he wants. You're just conveniently ignoring half the question. – Lightness Races in Orbit Nov 17 '11 at 18:36
  • No, you're absolutely being petty. A direct question was asked, a direct answer was given. Just because the OP's example isn't satisfiable doesn't mean the question wasn't answered accurately. – ildjarn Nov 17 '11 at 18:37
  • Nonsense, and I shan't argue about it any more. There is really no need for you to get personal just because somebody downvoted your answer. – Lightness Races in Orbit Nov 17 '11 at 18:38
  • I'm not getting personal, but when someone asks "here's what I want to do, is it possible?" and the answer is "here's the only thing that's possible that remotely resembles what you're asking for", if you can't see the obvious answer to the question in that response then that's simply a massive logic failure on your part. /shrug – ildjarn Nov 17 '11 at 18:41
  • Calling me "petty" is personal. – Lightness Races in Orbit Nov 17 '11 at 18:41
  • _petty (adj.): (of behavior) Characterized by an undue concern for trivial matters_ Sounds like an accurate observation to me. – ildjarn Nov 17 '11 at 18:42
  • I never said it wasn't accurate. I said it was personal. – Lightness Races in Orbit Nov 17 '11 at 18:43
  • @Tomalak and also the `{1,2}` was from a *counter* example of how to *not* do it. – Johannes Schaub - litb Nov 17 '11 at 20:08
  • @JohannesSchaub-litb: That no less defines what "it" is. – Lightness Races in Orbit Nov 17 '11 at 20:11
-2

No. It's not.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 4
    You're *not* getting an upvote for that. Sometimes being right is not enough :-) – Kerrek SB Nov 17 '11 at 18:01
  • 2
    @KerrekSB: I think you'll find that this is as correct and accurate and useful as any C++98 answer is going to get! – Lightness Races in Orbit Nov 17 '11 at 18:02
  • C++98 did already allow the array() syntax explained in the other answer. it just wasn't called value initialization. so as the question is posed, the answer should be "yes it is possible" – Johannes Schaub - litb Nov 17 '11 at 18:17
  • @JohannesSchaub-litb But not usefully:-). (Why would you want an array whose values can only be `0`?) Other solutions _are_ possible, however; the flat statement that it's not possible is wrong, at least from a practical point of view. (Technically, you use a `struct`, rather than an array, but if all the `struct` contains is the array, it comes out to the same thing.) – James Kanze Nov 17 '11 at 18:23
  • @james i agree and if i wouldnt.be.in a train on a.phone i would.already have posted that :-X – Johannes Schaub - litb Nov 17 '11 at 18:27
  • @JohannesSchaub-litb: The OP specifically gave the example of `{1,2}`. No solution to do this has been proposed. – Lightness Races in Orbit Nov 17 '11 at 18:32
  • @TomalakGeret'kal My solution using a `struct` works fine for this; all you have to do is define a static instance of the `struct`, initialized with `{ 1, 2 }`. – James Kanze Nov 17 '11 at 18:36