Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #87192 > unrolled thread

What is this header good for ?

Started byBonita Montero <Bonita.Montero@gmail.com>
First post2022-11-01 15:32 +0100
Last post2022-11-06 10:34 +0100
Articles 19 — 5 participants

Back to article view | Back to comp.lang.c++


Contents

  What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-01 15:32 +0100
    Re: What is this header good for ? "Alf P. Steinbach" <alf.p.steinbach@gmail.com> - 2022-11-01 20:23 +0100
      Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-02 03:59 +0100
        Re: What is this header good for ? Tony Oliver <guinness.tony@gmail.com> - 2022-11-02 04:45 -0700
          Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-02 14:33 +0100
    Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-02 04:02 +0100
      Re: What is this header good for ? Muttley@dastardlyhq.com - 2022-11-02 16:59 +0000
        Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-02 18:45 +0100
          Re: What is this header good for ? Öö Tiib <ootiib@hot.ee> - 2022-11-03 08:22 -0700
            Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-03 16:43 +0100
              Re: What is this header good for ? Öö Tiib <ootiib@hot.ee> - 2022-11-03 09:06 -0700
                Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-04 20:12 +0100
                  Re: What is this header good for ? Öö Tiib <ootiib@hot.ee> - 2022-11-05 06:24 -0700
                    Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-05 15:51 +0100
                      Re: What is this header good for ? Öö Tiib <ootiib@hot.ee> - 2022-11-05 09:44 -0700
                        Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-05 18:11 +0100
                          Re: What is this header good for ? Öö Tiib <ootiib@hot.ee> - 2022-11-05 16:03 -0700
                            Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-06 06:19 +0100
                            Re: What is this header good for ? Bonita Montero <Bonita.Montero@gmail.com> - 2022-11-06 10:34 +0100

#87192 — What is this header good for ?

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-01 15:32 +0100
SubjectWhat is this header good for ?
Message-ID<tjrakt$q076$1@dont-email.me>
#pragma once
#include <type_traits>

template<typename T>
#if defined(__cpp_concpets)
	requires std::is_scalar_v<T>
#endif
union ndi_t
{
	ndi_t() = default;
	ndi_t( T init );
	ndi_t &operator =( T assign );
	operator T();
	T *operator &();
private:
	T m_value;
};

template<typename T>
#if defined(__cpp_concpets)
	requires std::is_scalar_v<T>
#endif
inline ndi_t<T>::ndi_t( T init ) :
	m_value( init )
{
}

template<typename T>
#if defined(__cpp_concpets)
	requires std::is_scalar_v<T>
#endif
inline ndi_t<T> & ndi_t<T>::operator =( T assign )
{
	m_value = assign;
	return *this;
}

template<typename T>
#if defined(__cpp_concpets)
	requires std::is_scalar_v<T>
#endif
inline ndi_t<T>::operator T()
{
	return m_value;
}

template<typename T>
#if defined(__cpp_concpets)
	requires std::is_scalar_v<T>
#endif
inline T *ndi_t<T>::operator &()
{
	return &m_value;
}

[toc] | [next] | [standalone]


#87193

From"Alf P. Steinbach" <alf.p.steinbach@gmail.com>
Date2022-11-01 20:23 +0100
Message-ID<tjrrnu$r9rf$1@dont-email.me>
In reply to#87192
On 1 Nov 2022 15:32, Bonita Montero wrote:
> #if defined(__cpp_concpets)

That loooks lik a speling eror.

A good-for-nothing header then.

Cheers!,

- Alf

[toc] | [prev] | [next] | [standalone]


#87194

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-02 03:59 +0100
Message-ID<tjsmdf$vv77$3@dont-email.me>
In reply to#87193
Am 01.11.2022 um 20:23 schrieb Alf P. Steinbach:

> On 1 Nov 2022 15:32, Bonita Montero wrote:

>> #if defined(__cpp_concpets)

> That loooks lik a speling eror.

That's a feature-test macro defined by C++20.

> A good-for-nothing header then.

Thanks for your effort to have a deep understanding of my code. !

[toc] | [prev] | [next] | [standalone]


#87196

FromTony Oliver <guinness.tony@gmail.com>
Date2022-11-02 04:45 -0700
Message-ID<200d5938-8af5-4b2a-b37d-6b3b8d36b03fn@googlegroups.com>
In reply to#87194
On Wednesday, 2 November 2022 at 02:59:13 UTC, Bonita Montero wrote:
> Am 01.11.2022 um 20:23 schrieb Alf P. Steinbach: 
> 
> > On 1 Nov 2022 15:32, Bonita Montero wrote: 
> 
> >> #if defined(__cpp_concpets) 
> 
> > That loooks lik a speling eror.
> That's a feature-test macro defined by C++20. 

No, it isn't.  You seem to be trying (and failing) to spell "__cpp_concepts".
"__cpp_concpets" does not appear anywhere in N4860.

[toc] | [prev] | [next] | [standalone]


#87197

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-02 14:33 +0100
Message-ID<tjtrir$16ctt$1@dont-email.me>
In reply to#87196
Am 02.11.2022 um 12:45 schrieb Tony Oliver:
> On Wednesday, 2 November 2022 at 02:59:13 UTC, Bonita Montero wrote:
>> Am 01.11.2022 um 20:23 schrieb Alf P. Steinbach:
>>
>>> On 1 Nov 2022 15:32, Bonita Montero wrote:
>>
>>>> #if defined(__cpp_concpets)
>>
>>> That loooks lik a speling eror.
>> That's a feature-test macro defined by C++20.
> 
> No, it isn't.  You seem to be trying (and failing) to spell "__cpp_concepts".
> "__cpp_concpets" does not appear anywhere in N4860.

Ok, I removed it anyway, requiring concepts always now because
I'm using a concept which should stop specializations under a
certain condition.

[toc] | [prev] | [next] | [standalone]


#87195

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-02 04:02 +0100
Message-ID<tjsmkg$1004m$1@dont-email.me>
In reply to#87192
That's the final version of my header, now it requires C++20:

#pragma once
#include <type_traits>

template<typename T>
	requires std::is_trivially_destructible_v<T>
union ndi_t
{
	ndi_t();
	ndi_t( T const &init );
	ndi_t &operator =( T const &assign );
	operator T &();
	T *operator &();
	T *operator ->()
		requires std::is_class_v<T>;
private:
	union U
	{
		U();
		U( T const &value );
		T m_value;
	} m_u;
};

template<typename T>
	requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::U::U()
{
}

template<typename T>
	requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::U::U( T const &value ) :
	m_value( value )
{
}

template<typename T>
	requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::ndi_t() :
	m_u()
{
}

template<typename T>
	requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::ndi_t( T const &init ) :
	m_u( init )
{
}

template<typename T>
	requires std::is_trivially_destructible_v<T>
inline ndi_t<T> & ndi_t<T>::operator =( T const &assign )
{
	m_u.value = assign;
	return *this;
}

template<typename T>
	requires std::is_trivially_destructible_v<T>
inline ndi_t<T>::operator T &()
{
	return m_u.m_value;
}

template<typename T>
	requires std::is_trivially_destructible_v<T>
inline T *ndi_t<T>::operator &()
{
	return &m_u.m_value;
}


template<typename T>
	requires std::is_trivially_destructible_v<T>
inline T *ndi_t<T>::operator ->()
	requires std::is_class_v<T>
{
	return &m_u.m_value;
}

[toc] | [prev] | [next] | [standalone]


#87198

FromMuttley@dastardlyhq.com
Date2022-11-02 16:59 +0000
Message-ID<tju7mb$1l95$1@gioia.aioe.org>
In reply to#87195
On Wed, 2 Nov 2022 04:02:53 +0100
Bonita Montero <Bonita.Montero@gmail.com> wrote:
>That's the final version of my header, now it requires C++20:

And this explosion in an ASCII factory does what exactly?

[toc] | [prev] | [next] | [standalone]


#87199

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-02 18:45 +0100
Message-ID<tjuabe$17gkq$1@dont-email.me>
In reply to#87198
Am 02.11.2022 um 17:59 schrieb Muttley@dastardlyhq.com:

> Bonita Montero <Bonita.Montero@gmail.com> wrote:

>> That's the final version of my header, now it requires C++20:

> And this explosion in an ASCII factory does what exactly?

It's a class that wraps simple types that don't have destructors and
omits their default-construction. With that you can f.e. have a vector
of ints (vector<ndi_t<int>>) and the ints aren't default-constructed,
i.e. their value is arbitrary.
That might save a lot of CPU-time if you grow a large vector in one
step so that you can omit the initialization if you do it yourself
anyway. But there are other standard types like pair<> where the
members are also default-initialized. So if you have a vector of
such pairs where .first and .second are ndi_t-types this also might
save some CPU-time.
There are a number of overloaded operators so that you can handle
such an ndi_t<>-object nearly the same way you would handle the
corresponding type it encapsulates. F.e. you can take the ndi_t<>
object's address with & and you get the address of the encapsulated
type. Or you can access the members of the encapsulated object if
it is a class type with the ->-operator, similar to a smart pointer.

[toc] | [prev] | [next] | [standalone]


#87206

FromÖö Tiib <ootiib@hot.ee>
Date2022-11-03 08:22 -0700
Message-ID<33a066b2-bdab-4423-97dd-36c2d96e431bn@googlegroups.com>
In reply to#87199
On Wednesday, 2 November 2022 at 19:45:33 UTC+2, Bonita Montero wrote:
> Am 02.11.2022 um 17:59 schrieb Mut...@dastardlyhq.com: 
> 
> > Bonita Montero <Bonita....@gmail.com> wrote: 
> 
> >> That's the final version of my header, now it requires C++20: 
> 
> > And this explosion in an ASCII factory does what exactly?
> It's a class that wraps simple types that don't have destructors and 
> omits their default-construction. With that you can f.e. have a vector 
> of ints (vector<ndi_t<int>>) and the ints aren't default-constructed, 
> i.e. their value is arbitrary.
> 
> That might save a lot of CPU-time if you grow a large vector in one 
> step so that you can omit the initialization if you do it yourself 
> anyway. 

How it "might"?  IMHO not with what vector is required to do. 
We grow by your example a vector like vec.resize(large_size). 
That calls void std::vector<T,A>::resize(size_type count, T value = T());
That function is required to copy construct each element that we
did grow using that "value" as argument. On our case that T is
supposed to be ndi_t<Something>. Therefore resize() will use
compiler-generated constructors 
ndi_t<Something>::ndi_t( ndit_t const &init ) and those are required
to diligently copy that uninitalized Something value from inside of
that T() object. So what you expect a compiler can "save" here
compared to std::vector<Something> ?

> But there are other standard types like pair<> where the 
> members are also default-initialized. So if you have a vector of 
> such pairs where .first and .second are ndi_t-types this also might 
> save some CPU-time. 
> There are a number of overloaded operators so that you can handle 
> such an ndi_t<>-object nearly the same way you would handle the 
> corresponding type it encapsulates. F.e. you can take the ndi_t<> 
> object's address with & and you get the address of the encapsulated 
> type. Or you can access the members of the encapsulated object if 
> it is a class type with the ->-operator, similar to a smart pointer.

[toc] | [prev] | [next] | [standalone]


#87207

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-03 16:43 +0100
Message-ID<tk0nj8$1g58o$1@dont-email.me>
In reply to#87206
Am 03.11.2022 um 16:22 schrieb Öö Tiib:

> How it "might"?  IMHO not with what vector is required to do.
> We grow by your example a vector like vec.resize(large_size).
> That calls void std::vector<T,A>::resize(size_type count, T value = T());
> That function is required to copy construct each element that we
> did grow using that "value" as argument.

The default-constructor of my ndi_t<> is empty so that the loop initia-
lizing the new elements is optimized away. My ndi_t<> is a union so the
member m_value isn't initialized by default but needs explicit initali-
zation with the constructor of my union and I omit that.

[toc] | [prev] | [next] | [standalone]


#87209

FromÖö Tiib <ootiib@hot.ee>
Date2022-11-03 09:06 -0700
Message-ID<fc035527-6558-4ca4-ade9-e379a8bc065dn@googlegroups.com>
In reply to#87207
On Thursday, 3 November 2022 at 17:43:54 UTC+2, Bonita Montero wrote:
> Am 03.11.2022 um 16:22 schrieb Öö Tiib: 
> 
> > How it "might"? IMHO not with what vector is required to do. 
> > We grow by your example a vector like vec.resize(large_size). 
> > That calls void std::vector<T,A>::resize(size_type count, T value = T()); 
> > That function is required to copy construct each element that we 
> > did grow using that "value" as argument.
>
> The default-constructor of my ndi_t<> is empty so that the loop initia- 
> lizing the new elements is optimized away. My ndi_t<> is a union so the 
> member m_value isn't initialized by default but needs explicit initali- 
> zation with the constructor of my union and I omit that.

What? The resize() is required to copy construct new elements from 
"value" parameter, not default construct new elements. What default
constructor of ndi_t does does not matter in context where it is not
called.

[toc] | [prev] | [next] | [standalone]


#87235

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-04 20:12 +0100
Message-ID<tk3o67$1v8om$1@dont-email.me>
In reply to#87209
Am 03.11.2022 um 17:06 schrieb Öö Tiib:

> What? The resize() is required to copy construct new elements from
> "value" parameter, not default construct new elements. ...

The appended elements are initialized by default if you don't pass
a default-value given to the parametrized constructor. So you can
gigabytes of appended elements that aren't default-initialized and
when you have an operating system that overcommits the appended
memory pages aren't even assigned to physical pages until you
write-touch them.

[toc] | [prev] | [next] | [standalone]


#87250

FromÖö Tiib <ootiib@hot.ee>
Date2022-11-05 06:24 -0700
Message-ID<c061094f-7064-4913-a547-1a2ffa4d84e5n@googlegroups.com>
In reply to#87235
On Friday, 4 November 2022 at 21:12:23 UTC+2, Bonita Montero wrote:
> Am 03.11.2022 um 17:06 schrieb Öö Tiib: 
> 
> > What? The resize() is required to copy construct new elements from
> > "value" parameter, not default construct new elements. ... 
> 
> The appended elements are initialized by default if you don't pass 
> a default-value given to the parametrized constructor. So you can 
> gigabytes of appended elements that aren't default-initialized and 
> when you have an operating system that overcommits the appended 
> memory pages aren't even assigned to physical pages until you 
> write-touch them.

Plain wrong third time. That is not what resize is required to do. If you
omit the value parameter then it is required to default construct it and
then copy construct the result. Can be billions of times if you resized
to billions of elements. 

[toc] | [prev] | [next] | [standalone]


#87251

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-05 15:51 +0100
Message-ID<tk5t95$2gncr$1@dont-email.me>
In reply to#87250
Am 05.11.2022 um 14:24 schrieb Öö Tiib:

> Plain wrong third time. That is not what resize is required to do.

That depends on what you want. If you want the appended elements not to
be default-initialized because you overwrite the element yourself later
or you don't initialize it at all because you want partitially complete
pages which arent assigned to phyisical memory (unter Linux these pages
arent even reseved from swap with overcommitting) my ndi_t union is the
right thing.
The class only works if the encapsulated type has a trivial destructor
which is restricted by a concept to prevent to do the wrong things with
my union.

[toc] | [prev] | [next] | [standalone]


#87252

FromÖö Tiib <ootiib@hot.ee>
Date2022-11-05 09:44 -0700
Message-ID<9268ea98-1e79-492a-8f78-6ab52005a441n@googlegroups.com>
In reply to#87251
On Saturday, 5 November 2022 at 16:51:35 UTC+2, Bonita Montero wrote:
> Am 05.11.2022 um 14:24 schrieb Öö Tiib: 
> 
> > Plain wrong third time. That is not what resize is required to do.
>
> That depends on what you want.

Nope. If a function  is not required by standard to call your mutilated
default constructor then it does not start to call it (and optimize away)
because you want. Your wishes are irrelevant. 

[toc] | [prev] | [next] | [standalone]


#87253

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-05 18:11 +0100
Message-ID<tk65g1$2ik4v$1@dont-email.me>
In reply to#87252
Am 05.11.2022 um 17:44 schrieb Öö Tiib:

>> That depends on what you want.

> Nope. If a function  is not required by standard to call your mutilated
> default constructor then it does not start to call it (and optimize away)
> because you want. Your wishes are irrelevant.

Of course the default-construction loop on the appended elements
is optimized away, that's what my ndi_t<>-union is for; this saves
CPU time.
You simply don't understand the purpose.

[toc] | [prev] | [next] | [standalone]


#87263

FromÖö Tiib <ootiib@hot.ee>
Date2022-11-05 16:03 -0700
Message-ID<26dcb12b-18e1-4eca-8a12-85dd4ac414d7n@googlegroups.com>
In reply to#87253
On Saturday, 5 November 2022 at 19:11:47 UTC+2, Bonita Montero wrote:
> Am 05.11.2022 um 17:44 schrieb Öö Tiib: 
> 
> >> That depends on what you want. 
> 
> > Nope. If a function is not required by standard to call your mutilated 
> > default constructor then it does not start to call it (and optimize away) 
> > because you want. Your wishes are irrelevant.
>
> Of course the default-construction loop on the appended elements 
> is optimized away, that's what my ndi_t<>-union is for; this saves 
> CPU time. 

The resize has never been required to have default construction loop
in it; resize is required to have loop of copy initialization.

> You simply don't understand the purpose.

I perfectly understand that you wish that there is default construction
loop in vector resize, just that it is not so in our reality.   

[toc] | [prev] | [next] | [standalone]


#87265

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-06 06:19 +0100
Message-ID<tk7g59$2uu4h$1@dont-email.me>
In reply to#87263
Am 06.11.2022 um 00:03 schrieb Öö Tiib:

> The resize has never been required to have default construction loop
> in it; resize is required to have loop of copy initialization.

https://en.cppreference.com/w/cpp/container/vector/resize

"additional default-inserted elements are appended".

> I perfectly understand that you wish that there is default construction
> loop in vector resize, just that it is not so in our reality.

You're a idiot.

[toc] | [prev] | [next] | [standalone]


#87267

FromBonita Montero <Bonita.Montero@gmail.com>
Date2022-11-06 10:34 +0100
Message-ID<tk7v2o$evi$1@gioia.aioe.org>
In reply to#87263
I've written a little program to demonstrate the advantage of my ndi_t
union:

#include <iostream>
#include <vector>
#include <chrono>
#include <cmath>
#include <sstream>
#include "ndi_t.h"

using namespace std;
using namespace chrono;

int main()
{
	auto bench = []<typename T, typename Touch>( T t, Touch touch ) -> double
		requires requires( Touch touch, vector<T> &vt ) { { touch( vt ) }; }
	{
		constexpr size_t N = (size_t)1 << 30;
		vector<T> vt;
		auto start = high_resolution_clock::now();
		vt.resize( N );
		touch( vt );
		return (double)duration_cast<nanoseconds>(high_resolution_clock::now() 
- start).count() / 1.0e6;
	};
	auto ndiTouch = []( vector<ndi_t<char>> &ndiVec )
	{
		for( size_t i = 0; i < ndiVec.size(); ndiVec[i] = 0, i += 0x1000 );
	};
	double
		tChar = bench( char(), []( vector<char> const & ) {} ),
		tNdi = bench( ndi_t<char>(), []( vector<ndi_t<char>> const & ) {} ),
		tNdiTouch = bench( ndi_t<char>(), ndiTouch );
	cout << "char: " << tChar << "ms" << endl;
	cout << "ndi_t<char>: " << tNdi << "ms" << endl;
	cout << "ndi_t<char> (touch): " << tNdiTouch << "ms" << endl;
}

It benchmarks the time to resize a char-vector to one GB. My ndi_t
union is about 30.000 times faster on my Linux computer. This is
while such large allocations aren't pooled by your memory allocator
but directly fetched from the kernel in multiples of pages. If this
pages aren't touched they remain unassigned to actual physical memory.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web