Overview
Examples
Screenshots
Comparisons
Applications
Download
Documentation
Tutorials
Bazaar
Status & Roadmap
FAQ
Authors & License
Forums
Funding Ultimate++
Search on this site
Search in forums












SourceForge.net Logo
Home » U++ Library support » U++ Core » How to mark std::array<T, N> moveable if only T is moveable
How to mark std::array<T, N> moveable if only T is moveable [message #60668] Tue, 02 July 2024 17:54 Go to next message
busiek is currently offline  busiek
Messages: 70
Registered: February 2011
Location: Poland
Member
Hi all,
U++ does not have a container with std::array functionality. Is there any simple way to mark std::array<T, N> moveable if only T is moveable?
I didn't come with anything better than implementing my own version of std::array derived from Moveable<MyArray<T, N>>. By using macro NTL_MOVEABLE one can only mark moveable a specific type not a template. Even if I want to mark specific template type, macro does not work with template types having two or more parameters and I have to expand macro myself:
template<> inline void AssertMoveable<std::array<double, 2>>(std::array<double, 2>*) {}


Correct me if I miss something. Shouldn't the mechanism of marking type moveable be done through partial class instantiation? Or concepts with C++20?
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60669 is a reply to message #60668] Wed, 03 July 2024 03:39 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 656
Registered: March 2007
Contributor
Reminds me of some exploration I did with Moveable.

I vaguely recalled that when I tested a few years back, the way Moveable was designed were causing a compile time error with Windows/VSBuild. I would also welcome a redesign of Moveable using more recent language facilities.
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60682 is a reply to message #60669] Thu, 18 July 2024 08:41 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14255
Registered: November 2005
Ultimate Member
Lance wrote on Wed, 03 July 2024 03:39
Reminds me of some exploration I did with Moveable.

I vaguely recalled that when I tested a few years back, the way Moveable was designed were causing a compile time error with Windows/VSBuild. I would also welcome a redesign of Moveable using more recent language facilities.


Suggestions? (But it needs to be backward compatible).
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60683 is a reply to message #60668] Thu, 18 July 2024 08:44 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14255
Registered: November 2005
Ultimate Member
busiek wrote on Tue, 02 July 2024 17:54
Hi all,
U++ does not have a container with std::array functionality. Is there any simple way to mark std::array<T, N> moveable if only T is moveable?
I didn't come with anything better than implementing my own version of std::array derived from Moveable<MyArray<T, N>>. By using macro NTL_MOVEABLE one can only mark moveable a specific type not a template. Even if I want to mark specific template type, macro does not work with template types having two or more parameters and I have to expand macro myself:
template<> inline void AssertMoveable<std::array<double, 2>>(std::array<double, 2>*) {}


Correct me if I miss something. Shouldn't the mechanism of marking type moveable be done through partial class instantiation? Or concepts with C++20?


Wait a moment there: Are you sure that std::array is Moveable? There is no guarantee...

Mirek
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60686 is a reply to message #60683] Thu, 18 July 2024 19:39 Go to previous messageGo to next message
busiek is currently offline  busiek
Messages: 70
Registered: February 2011
Location: Poland
Member
I thought it was obvious if only T is moveable. In the reference for std::array it says it is an aggregate type for C-style array T[N]. What do you mean by guarantee?
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60688 is a reply to message #60686] Fri, 19 July 2024 13:11 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14255
Registered: November 2005
Ultimate Member
Same semantics does not cover U++ moveable. Now I agree it is unlikely, but so I thought about std::string until I met implementation that is not U++ moveable...
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60689 is a reply to message #60688] Fri, 19 July 2024 13:52 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 656
Registered: March 2007
Contributor
mirek wrote on Fri, 19 July 2024 07:11
Same semantics does not cover U++ moveable. Now I agree it is unlikely, but so I thought about std::string until I met implementation that is not U++ moveable...


I looked into std::basic_string in this post, message #59178.

Quote:

Story of std::basic_string (GLIBCXX implementation)

It's surprising that a basic_string<ch> would cause trouble (core dump etc) when treated as raw bytes. Digging into its implementation (in <bits/basic_string.h>), we have the data members
...
.

On the same post, I proposed to use class traits to handle Moveable. There are details I could not iron out. Also, it might not be compatible with very old c++ because I have an added goal to allow non-trivially relocatable class objects, which can be corrected pre- or post relocation, be housed in std::vector or upp::Vector.
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60690 is a reply to message #60689] Fri, 19 July 2024 14:02 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 656
Registered: March 2007
Contributor
last time I tested, AssertMoveable was preventing U++ be compiled with std=c++20. Eventually that might be a move we have to make.

[Updated on: Fri, 19 July 2024 14:02]

Report message to a moderator

Re: How to mark std::array<T, N> moveable if only T is moveable [message #60691 is a reply to message #60690] Fri, 19 July 2024 19:10 Go to previous messageGo to next message
Didier is currently offline  Didier
Messages: 725
Registered: November 2008
Location: France
Contributor
I dont know about std::array but std::Vector is not upp::moveable
I recently ran into it in Someone else's code... And I had to replace it with upp::Vector.

I agree with Lance: keeping up with latest compiler standards may be a good move

[Updated on: Fri, 19 July 2024 19:14]

Report message to a moderator

Re: How to mark std::array<T, N> moveable if only T is moveable [message #60693 is a reply to message #60690] Mon, 22 July 2024 11:10 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14255
Registered: November 2005
Ultimate Member
Lance wrote on Fri, 19 July 2024 14:02
last time I tested, AssertMoveable was preventing U++ be compiled with std=c++20. Eventually that might be a move we have to make.


I have just checked and it seems fine...
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60694 is a reply to message #60693] Tue, 23 July 2024 01:07 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 656
Registered: March 2007
Contributor
Sorry Mirek. I forgot to give more detail. It's been mentioned in this reply in the post I mentioned above. It happens when I compile theide (or anything use Core) with MSBT64x22. I haven't tried with more recent MSBuilder.

Lance wrote on Mon, 14 November 2022 08:52

Well it all starts with testing Upp code for C++20 compliance. let's try theide first. The ide compiles fine on both GCC and CLANG with -std=c++20 option, except some complaints on capturing this by default is deprecated in C++20, which are easy to fix or safe to ignore for now. But it's a total different story with MSC. with standard set to C++17, MSC rejects a bunch of stuff like
return somecondition? "a literal string" : AString;

These are also easy to fix if you don't mind your local version is slightly different from the main stream.

When standard is set to C++20 or c++latest, Upp::Moveable AssertMoveable0() is start to causing compilation failure, this one seems to be quite difficult to fix.

I was thinking it's just a mechanism to communicate to the compiler that it can treat object of this class as raw bytes, maybe we can do it differently with so much more facilities available in more recent c++ library.

So I start to do some experiment.

Re: How to mark std::array<T, N> moveable if only T is moveable [message #60696 is a reply to message #60682] Tue, 23 July 2024 18:25 Go to previous messageGo to next message
busiek is currently offline  busiek
Messages: 70
Registered: February 2011
Location: Poland
Member
mirek wrote on Thu, 18 July 2024 08:41
Lance wrote on Wed, 03 July 2024 03:39
Reminds me of some exploration I did with Moveable.

I vaguely recalled that when I tested a few years back, the way Moveable was designed were causing a compile time error with Windows/VSBuild. I would also welcome a redesign of Moveable using more recent language facilities.


Suggestions? (But it needs to be backward compatible).


I was thinking about something like that:
#include <Core/Core.h>
#include <type_traits>

namespace Upp {
// First way of marking class moveable is to be an ancestor of NtlMoveableBase
template <class T> class NtlMoveableBase {};

// Second way is to specialize NtlMoveableClass
template <class T>
struct NtlMoveableClass
: std::integral_constant<bool,
	   std::is_trivial_v<T>
	|| std::is_base_of_v<Upp::NtlMoveableBase<T>, T>
	// below is not needed if we make them derived from NtlMoveableBase
	|| std::is_base_of_v<Upp::Moveable_<T>, T>
	|| std::is_base_of_v<Upp::Moveable<T>, T>
	|| std::is_base_of_v<Upp::MoveableAndDeepCopyOption<T>, T>> {};

// For instance mark std::array<T, N> moveable if only T is moveable
template <class T, size_t N>
struct NtlMoveableClass<std::array<T, N>>
: std::integral_constant<bool, NtlMoveableClass<T>::value> {};

// Helper for checking whether class is moveable
template <class T>
inline constexpr bool IsNtlMoveable = NtlMoveableClass<T>::value;

// Optional concept for c++20
template <class T>
concept NtlMoveable = IsNtlMoveable<T>;

}

using namespace Upp;

// use of concept
template <NtlMoveable T>
struct MyVector
{
	T *ptr;
	// Or use static_assert
	~MyVector() { static_assert(IsNtlMoveable<T>); }
};

CONSOLE_APP_MAIN
{
	// Checking if given type is moveable
	static_assert(IsNtlMoveable<int>);
	static_assert(IsNtlMoveable<const void *>);
	static_assert(IsNtlMoveable<Vector<int>>);
	static_assert(IsNtlMoveable<std::array<int, 5>>);
	static_assert(IsNtlMoveable<std::array<Vector<int>, 5>>);
	static_assert(!IsNtlMoveable<Thread>);
}

You could redefine NTL_MOVEABLE macro as a specialization of NtlMoveableClass.
But you need to change an assertion AssertMoveable((T*)0) to static_assert(IsNtlMoveable<T>).
Are those ideas usable?
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60700 is a reply to message #60696] Thu, 25 July 2024 02:27 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14255
Registered: November 2005
Ultimate Member
busiek wrote on Tue, 23 July 2024 18:25
mirek wrote on Thu, 18 July 2024 08:41
Lance wrote on Wed, 03 July 2024 03:39
Reminds me of some exploration I did with Moveable.

I vaguely recalled that when I tested a few years back, the way Moveable was designed were causing a compile time error with Windows/VSBuild. I would also welcome a redesign of Moveable using more recent language facilities.


Suggestions? (But it needs to be backward compatible).


I was thinking about something like that:
#include <Core/Core.h>
#include <type_traits>

namespace Upp {
// First way of marking class moveable is to be an ancestor of NtlMoveableBase
template <class T> class NtlMoveableBase {};

// Second way is to specialize NtlMoveableClass
template <class T>
struct NtlMoveableClass
: std::integral_constant<bool,
	   std::is_trivial_v<T>
	|| std::is_base_of_v<Upp::NtlMoveableBase<T>, T>
	// below is not needed if we make them derived from NtlMoveableBase
	|| std::is_base_of_v<Upp::Moveable_<T>, T>
	|| std::is_base_of_v<Upp::Moveable<T>, T>
	|| std::is_base_of_v<Upp::MoveableAndDeepCopyOption<T>, T>> {};

// For instance mark std::array<T, N> moveable if only T is moveable
template <class T, size_t N>
struct NtlMoveableClass<std::array<T, N>>
: std::integral_constant<bool, NtlMoveableClass<T>::value> {};

// Helper for checking whether class is moveable
template <class T>
inline constexpr bool IsNtlMoveable = NtlMoveableClass<T>::value;

// Optional concept for c++20
template <class T>
concept NtlMoveable = IsNtlMoveable<T>;

}

using namespace Upp;

// use of concept
template <NtlMoveable T>
struct MyVector
{
	T *ptr;
	// Or use static_assert
	~MyVector() { static_assert(IsNtlMoveable<T>); }
};

CONSOLE_APP_MAIN
{
	// Checking if given type is moveable
	static_assert(IsNtlMoveable<int>);
	static_assert(IsNtlMoveable<const void *>);
	static_assert(IsNtlMoveable<Vector<int>>);
	static_assert(IsNtlMoveable<std::array<int, 5>>);
	static_assert(IsNtlMoveable<std::array<Vector<int>, 5>>);
	static_assert(!IsNtlMoveable<Thread>);
}

You could redefine NTL_MOVEABLE macro as a specialization of NtlMoveableClass.
But you need to change an assertion AssertMoveable((T*)0) to static_assert(IsNtlMoveable<T>).
Are those ideas usable?


Yep. After tinkering and simplifying I think this should cover it all:

template <class T> struct Moveable {};

template <class T>
inline constexpr bool is_Moveable = std::is_trivially_copyable<T>::value ||
                                    std::is_base_of<moveable<T>, T>::value;


We will not need NTL_MOVEABLE macro anyway... Trivial types are covered and allowing non-trivial types to be explicitly marked Moveable is outright dangerous.

BTW, std::array passes is_Moveable out of box.

See any problem? (Apart for requiring C++17, but I guess we can go there for the next release)

Mirek
icon14.gif  Re: How to mark std::array<T, N> moveable if only T is moveable [message #60701 is a reply to message #60700] Thu, 25 July 2024 03:16 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 656
Registered: March 2007
Contributor
It works!

The capability to manually mark a class might still be an asset. Suppose we receive a third party class whose objects are trivially relocatable but not trivially copyable, the simplest way to make Upp::Vector accept it is to mark it. Wrongfully marked class will usually result in immediate runtime error, hence should not be a big concern.
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60702 is a reply to message #60701] Thu, 25 July 2024 09:19 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14255
Registered: November 2005
Ultimate Member
Lance wrote on Thu, 25 July 2024 03:16

The capability to manually mark a class might still be an asset. Suppose we receive a third party class whose objects are trivially relocatable but not trivially copyable, the simplest way to make Upp::Vector accept it is to mark it. Wrongfully marked class will usually result in immediate runtime error, hence should not be a big concern.


I disagree. They might be relocatable in that version of library with given compiler only. Immediate runtime error might happen when you do testing, but developer might not be even aware he is supposed to test it.

Also from practical point of view, this never happened Smile

What might be usefull though is the capability to manually mark a class to be relocated by regular move/copy constructor:

- I still think it is a good idea not to do move/copy as default option to force effectivness

- but this would allow things like Vector<std::string> with some performance penalty...

Another thing to consider: Tuple is moveable if all its components are moveable. Are we able to express that somehow? (If not, no big deal, I can make Tuple moveable and request that elements are).

Mirek

[Updated on: Thu, 25 July 2024 09:33]

Report message to a moderator

Re: How to mark std::array<T, N> moveable if only T is moveable [message #60703 is a reply to message #60702] Thu, 25 July 2024 09:32 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14255
Registered: November 2005
Ultimate Member
mirek wrote on Thu, 25 July 2024 09:19

Another thing to consider: Tuple is moveable if all its components are moveable. Are we able to express that somehow? (If not, no big deal, I can make Tuple moveable and request that elements are).


Figured it out:


struct not_moveable {};

template <class A, class B>
class Two : std::conditional<is_moveable<A> && is_moveable<B>, moveable<Two<A, B>>, not_moveable>::type {
	A a;
	B b;
};


[Updated on: Thu, 25 July 2024 09:32]

Report message to a moderator

Re: How to mark std::array<T, N> moveable if only T is moveable [message #60704 is a reply to message #60703] Thu, 25 July 2024 10:07 Go to previous messageGo to next message
mirek is currently offline  mirek
Messages: 14255
Registered: November 2005
Ultimate Member
// For instance mark std::array<T, N> moveable if only T is moveable
template <class T, size_t N>
struct NtlMoveableClass<std::array<T, N>>
: std::integral_constant<bool, NtlMoveableClass<T>::value> {};


BTW, easiest and really nice way how to add optional trait:

template <> inline constexpr bool is_moveable<std::string> = true;


(do not want this, but could be useful to know)
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60706 is a reply to message #60703] Thu, 25 July 2024 17:32 Go to previous messageGo to next message
busiek is currently offline  busiek
Messages: 70
Registered: February 2011
Location: Poland
Member
mirek wrote on Thu, 25 July 2024 09:32
mirek wrote on Thu, 25 July 2024 09:19

Another thing to consider: Tuple is moveable if all its components are moveable. Are we able to express that somehow? (If not, no big deal, I can make Tuple moveable and request that elements are).


Figured it out:


struct not_moveable {};

template <class A, class B>
class Two : std::conditional<is_moveable<A> && is_moveable<B>, moveable<Two<A, B>>, not_moveable>::type {
	A a;
	B b;
};




But what if one wants to use std::tuple instead of Upp::Tuple? How to mark it moveable if tuple components are moveable?
I sometimes prefer to use std::tuple because one can write:
auto [a, b] = some std::tuple

Alternatively, there is a way to implement Upp::Tuple that it works with structured binding?
Re: How to mark std::array<T, N> moveable if only T is moveable [message #60707 is a reply to message #60704] Fri, 26 July 2024 00:00 Go to previous messageGo to next message
Lance is currently offline  Lance
Messages: 656
Registered: March 2007
Contributor
mirek wrote on Thu, 25 July 2024 04:07
// For instance mark std::array<T, N> moveable if only T is moveable
template <class T, size_t N>
struct NtlMoveableClass<std::array<T, N>>
: std::integral_constant<bool, NtlMoveableClass<T>::value> {};


BTW, easiest and really nice way how to add optional trait:

template <> inline constexpr bool is_moveable<std::string> = true;


(do not want this, but could be useful to know)


Exactly, like it or not, a programmer can mark a class as moveable.

Another not very convincing example.

#include <iostream>
#include <type_traits>
#include <array>


template <class T> struct Moveable {};

template <class T>
inline constexpr bool is_moveable_v = std::is_trivially_copyable<T>::value ||
                                    std::is_base_of<Moveable<T>, T>::value;

class C: public Moveable<C>{
	C(const C& c){}
	C(C&& c){}
};

// uncomment to communicate the moveability of array<T,n> to the compiler
//template <class T, int n>
//inline constexpr bool is_moveable_v<std::array<T,n>> = is_moveable_v<T>;

int main()
{
	std::cout<<is_moveable_v<std::array<C,5>><<std::endl;
}


Re: How to mark std::array<T, N> moveable if only T is moveable [message #60714 is a reply to message #60703] Mon, 29 July 2024 08:47 Go to previous messageGo to previous message
mirek is currently offline  mirek
Messages: 14255
Registered: November 2005
Ultimate Member
mirek wrote on Thu, 25 July 2024 09:32
mirek wrote on Thu, 25 July 2024 09:19

Another thing to consider: Tuple is moveable if all its components are moveable. Are we able to express that somehow? (If not, no big deal, I can make Tuple moveable and request that elements are).


Figured it out:


struct not_moveable {};

template <class A, class B>
class Two : std::conditional<is_moveable<A> && is_moveable<B>, moveable<Two<A, B>>, not_moveable>::type {
	A a;
	B b;
};




Nicer and simpler way:

template <class A, class B> inline constexpr bool is_moveable<Two<A, B>> = is_moveable<A> && is_moveable<B>;


I am about ready to try to introduce this into U++, but I am actually out of ideas how to name things....

Moveable / is_moveable is not perfect (future c++ might name this trivially_relocatable, but that is too long IMO), but u++ traditional, I guess I can live that.

However, new system should introduce a trait that says "I know I cannot memmove this type, but I still would like to store it into Vector anyway". E.g. to have Index<std::string> ... Really not sure what id should I use for that... Something like "is_vector_compatible_but_slower", or "std_moveable" or something?

(alternative would be to have "mem moveable" as option, but I want to force developer to be explicit, not to forget to mark moveable types)

Mirek
Previous Topic: Copy the content of a SortedVectorMap
Next Topic: SMTP not working
Goto Forum:
  


Current Time: Mon Apr 28 15:30:24 CEST 2025

Total time taken to generate the page: 0.01005 seconds