Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

initialization and copying of class array member

58 views
Skip to first unread message

wyn...@gmail.com

unread,
Mar 16, 2019, 12:50:00 AM3/16/19
to
I'm trying implementing a fixed-size matrix class. But before that,
I should implement a fixed size 'vector' class template.
From the very begining of the impl., I feel copy ctor and linitializer_list
ctor are somewhat inefficient because they use loop instead of direct
element-wise copy which I thought might be possible(or not? because C array
is not assignable). Do I have to do it this way?

template<typename T, size_t N>
class Vect {
T m_arr[N];

public:
Vect() {};
Vect(const Vect& s) {
for(size_t i=0; i<N; ++i) {
m_arr[i]=s.m_arr[i];
}
};
Vect(std::initializer_list<T> s) {
T* wptr=m_arr;
for(const T* iptr=s.begin(); iptr<s.end(); ++iptr) {
*wptr=*iptr; ++wptr;
}
};

Vect& operator=(const Vect& s) { /*same as ctor */ };
Vect& operator=(std::initializer_list<T> s) { /*same as cotr*/ };
};

E.g.
Vect<float,3> arr{1,2,3},arr2(arr);
arr={3,4,5}; // assignment has the same efficiency issue
arr=arr2;

The second problem is when T is integer type or float type, can I use
memcpy from the argument s?

E.g.
Vect(const Vect& s) {
memcpy(m_arr,s.m_arr,sizeof(m_arr));
};
Vect(std::initializer_list<T> s) {
memcpy(m_arr,s.begin,sizeof(m_arr));
};

Juha Nieminen

unread,
Mar 16, 2019, 1:04:37 PM3/16/19
to
wyn...@gmail.com wrote:
> because C array is not assignable

If you want an assignable C-style static array, use std::array.
(It has all the same characteristics as a "raw" array, except
that it's directly copyable and assignable.)

--- news://freenews.netfront.net/ - complaints: ne...@netfront.net ---

john...@nowhere.co.uk

unread,
Mar 17, 2019, 12:55:23 PM3/17/19
to
On Sat, 16 Mar 2019 17:04:24 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>wyn...@gmail.com wrote:
>> because C array is not assignable
>
>If you want an assignable C-style static array, use std::array.
>(It has all the same characteristics as a "raw" array, except
>that it's directly copyable and assignable.)

It has a problem in that its allocated on the heap. Though obviously that'll
only work for contained objects where it can set their allocator which means
you could end up with a bit of a mess memory wise with the array itself on
the heap but contained objects having storage on the stack.

Alf P. Steinbach

unread,
Mar 17, 2019, 1:34:52 PM3/17/19
to
On 17.03.2019 17:55, john...@nowhere.co.uk wrote:
> On Sat, 16 Mar 2019 17:04:24 +0000 (UTC)
> Juha Nieminen <nos...@thanks.invalid> wrote:
>> wyn...@gmail.com wrote:
>>> because C array is not assignable
>>
>> If you want an assignable C-style static array, use std::array.
>> (It has all the same characteristics as a "raw" array, except
>> that it's directly copyable and assignable.)
>
> It has a problem in that its allocated on the heap.

Please, what materials or which college course (at which university) are
you learning from?

You've been taught a load of bollocks.

It can be very useful to the community to learn how that came about.


> Though obviously that'll
> only work for contained objects where it can set their allocator which means
> you could end up with a bit of a mess memory wise with the array itself on
> the heap but contained objects having storage on the stack.


Cheers!,

- Alf

Vir Campestris

unread,
Mar 17, 2019, 5:26:17 PM3/17/19
to
On 16/03/2019 17:04, Juha Nieminen wrote:
> wyn...@gmail.com wrote:
>> because C array is not assignable
>
> If you want an assignable C-style static array, use std::array.
> (It has all the same characteristics as a "raw" array, except
> that it's directly copyable and assignable.)
>
I beg to differ.

I just planted a C-style array because it was the only thing that could
be constexpr. (I wanted a map, but as it's rarely used I felt the cost
of copying it to the heap wasn't worth the RAM).

Andy

Ralf Goertz

unread,
Mar 18, 2019, 3:50:03 AM3/18/19
to
Am Sun, 17 Mar 2019 21:26:10 +0000
schrieb Vir Campestris <vir.cam...@invalid.invalid>:
Hm,

constexpr std::array<int,3> a{{3,42,1}};

seems to be compiling fine whereas

constexpr std::array<std::string,3> b{"3","42","1"};

gives

error: the type ‘const std::array<std::__cxx11::basic_string<char>, 3>’ of constexpr variable ‘b’ is not lite
ral

but so does

constexpr std::string b[]{"3","42","1"};

I don't see a difference. Did I misunderstand?

Chris Vine

unread,
Mar 18, 2019, 7:01:42 AM3/18/19
to
A constexpr variable must be a literal type. std::string is not a
literal type. int (and const char* instantiated with a C literal
string) is a literal type. So is a C array of literal types; and as I
understand it also a std::array of literal types, because std::array is
an aggregate type with implicit destructor.

Öö Tiib

unread,
Mar 18, 2019, 7:19:18 AM3/18/19
to
It is may be worth to note that std::string_view is literal type that
gets common use-cases covered. Like:

#include <iostream>
#include <string>
#include <array>

constexpr std::array<std::string_view, 3> arr{"3","42","1"};

int main()
{
for (auto s : arr)
{
std::cout << s << std::endl;
}
}


Öö Tiib

unread,
Mar 18, 2019, 7:48:37 AM3/18/19
to
If you need examples of how to make (compile time comparable,
searchable and foldable) maps then Boost.Hana contains one.

James Kuyper

unread,
Mar 18, 2019, 8:15:09 AM3/18/19
to
Unlike most of the other standard containers, nowhere in the description
of std::array is any mention made of an allocator. It's class template
does not take any Allocator type argument, None of it's member functions
takes an allocator argument or returns an allocator reference. That's as
close as C++ ever comes, for any type, to specifying that memory is not
dynamically allocated by this class. Because of what the standard does
NOT say about such things, a conforming implementation could still
allocate the memory dynamically, but the nature of this class provides
no obvious reason to do so.

john...@nowhere.co.uk

unread,
Mar 18, 2019, 8:55:01 AM3/18/19
to
On Sun, 17 Mar 2019 18:34:40 +0100
"Alf P. Steinbach" <alf.p.stein...@gmail.com> wrote:
>On 17.03.2019 17:55, john...@nowhere.co.uk wrote:
>> On Sat, 16 Mar 2019 17:04:24 +0000 (UTC)
>> Juha Nieminen <nos...@thanks.invalid> wrote:
>>> wyn...@gmail.com wrote:
>>>> because C array is not assignable
>>>
>>> If you want an assignable C-style static array, use std::array.
>>> (It has all the same characteristics as a "raw" array, except
>>> that it's directly copyable and assignable.)
>>
>> It has a problem in that its allocated on the heap.
>
>Please, what materials or which college course (at which university) are
>you learning from?
>
>You've been taught a load of bollocks.
>
>It can be very useful to the community to learn how that came about.

Note to self - don't post when its late. Swap heap and stack in that post.

Ralf Goertz

unread,
Mar 18, 2019, 9:46:31 AM3/18/19
to
Am Mon, 18 Mar 2019 11:01:21 +0000
Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:

> A constexpr variable must be a literal type. std::string is not a
> literal type. int (and const char* instantiated with a C literal
> string) is a literal type. So is a C array of literal types; and as I
> understand it also a std::array of literal types, because std::array
> is an aggregate type with implicit destructor.

I still don't get what you are saying. Assuming the "it" on the
penultimate lines is supposed to be an "is", aren't you claiming now
that a C array of const char* and array<const char *,int> can both be
constexpr?

How does this relate to your previous statement?:

>>> I just planted a C-style array because it was the only thing that
>>> could be constexpr. (I wanted a map, but as it's rarely used I felt
>>> the cost of copying it to the heap wasn't worth the RAM).

In fact, both lines below compile just fine.

constexpr std::array<const char*,3> b{"3","42","1"};
constexpr const char* c[]{"3","42","1"};


Chris Vine

unread,
Mar 18, 2019, 9:58:11 AM3/18/19
to
Whichever way around you meant it, you still have something not quite
right in your mental image of this. For the future, (a) if you want to
put stack-allocated objects into a container allocated on the heap and
have their lifetime tied to the lifetime of the container, copy or move
the objects into the container (C++ is pass by value), and (b) if you
want to put heap-allocated objects into a container allocated on the
stack and have their lifetime tied to the lifetime of the container,
pass them by std::unique_ptr, std::shared_ptr or some other handle
class.

Case (b) (the one which you now say you intended to refer to) happens
but is not as common in idiomatic C++ as you might think because, with
C++11 move semantics, most classes comprising internals allocated on the
heap come with moveable value-type wrappers. An example is std::string:
subject to the small string optimization, the bytes of the underlying
string are allocated on the heap but the std::string type is a type
which can be moved into a container in a way which amounts to a passing
of internal pointers together with an internal int or two.

Chris Vine

unread,
Mar 18, 2019, 10:10:23 AM3/18/19
to
On Mon, 18 Mar 2019 14:46:21 +0100
Ralf Goertz <m...@myprovider.invalid> wrote:
> Am Mon, 18 Mar 2019 11:01:21 +0000
> Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
>
> > A constexpr variable must be a literal type. std::string is not a
> > literal type. int (and const char* instantiated with a C literal
> > string) is a literal type. So is a C array of literal types; and as I
> > understand it also a std::array of literal types, because std::array
> > is an aggregate type with implicit destructor.
>
> I still don't get what you are saying. Assuming the "it" on the
> penultimate lines is supposed to be an "is", aren't you claiming now
> that a C array of const char* and array<const char *,int> can both be
> constexpr?

I am saying that, yes, provided they are initialized by a C string
literal.

(For what it is worth, the 'it' is correct gramatically - there is an
implicit repeat of the "so is" from the preceding part of the sentence,
which is a form of elision which maybe does not exist in German.)

> How does this relate to your previous statement?:

I didn't make a previous statement. I was answering what I perceived
to be your perplexity over the fact that std::array<int,n> could be
constexpr but std::array<std::string,n> could not. If that is not what
you meant then I don't understand your post.

> >>> I just planted a C-style array because it was the only thing that
> >>> could be constexpr. (I wanted a map, but as it's rarely used I felt
> >>> the cost of copying it to the heap wasn't worth the RAM).
>
> In fact, both lines below compile just fine.
>
> constexpr std::array<const char*,3> b{"3","42","1"};
> constexpr const char* c[]{"3","42","1"};

Indeed they do, as they should, because they are initialized by C string
literals.

Ralf Goertz

unread,
Mar 18, 2019, 11:34:17 AM3/18/19
to
Am Mon, 18 Mar 2019 14:10:09 +0000
schrieb Chris Vine <chris@cvine--nospam--.freeserve.co.uk>:

> On Mon, 18 Mar 2019 14:46:21 +0100
> Ralf Goertz <m...@myprovider.invalid> wrote:
> > Am Mon, 18 Mar 2019 11:01:21 +0000
> > Chris Vine <chris@cvine--nospam--.freeserve.co.uk> wrote:
> >
> > > A constexpr variable must be a literal type. std::string is not a
> > > literal type. int (and const char* instantiated with a C literal
> > > string) is a literal type. So is a C array of literal types; and
> > > as I understand it also a std::array of literal types, because
> > > std::array is an aggregate type with implicit destructor.
> >
> > I still don't get what you are saying. Assuming the "it" on the
> > penultimate lines is supposed to be an "is", aren't you claiming now
> > that a C array of const char* and array<const char *,int> can both
> > be constexpr?
>
> I am saying that, yes, provided they are initialized by a C string
> literal.
>
> (For what it is worth, the 'it' is correct gramatically - there is an
> implicit repeat of the "so is" from the preceding part of the
> sentence, which is a form of elision which maybe does not exist in
> German.)

Yes, thanks. I shouldn't try to correct a native speaker. After
rereading your sentence I fail to see what was bugging me in the first
place.

> > How does this relate to your previous statement?:
>
> I didn't make a previous statement.

I am sorry, you're right, that was Andy.

> I was answering what I perceived to be your perplexity over the fact
> that std::array<int,n> could be constexpr but
> std::array<std::string,n> could not. If that is not what you meant
> then I don't understand your post.

Actually, I was not perplexed about that. I merely wanted to give
examples of what can and what cannot be constexpr and state that I found
no difference between the two with respect to C and C++ style arrays. My
confusion was and remains to be what Andy said. The answer to you is
irrelevant as I thought I was talking to Andy.


Vir Campestris

unread,
Mar 18, 2019, 5:27:09 PM3/18/19
to
Interesting.

IIRC (and I don't have the code to hand) it was

std::array<std::pair<const char*, enumtype> , 8> lookup = {{"a", ea},
{"b", eb} (etc)

OTOH for various reasons we're on GCC 4 (yes, FOUR!) and some of us are
trying to drag the codebase kicking and screaming into the modern age.
Perhaps it was the old compiler.

Andy
--
(The code is at work, and I'm at home now)
0 new messages