#priorities ambiguous constructors

77 messages · Page 1 of 1 (latest)

opaque horizon
#

I have a problem i have some constructors that are ambiguous one that cast normally and one that tries to reinterpret cast any object this is a simplified version I tried to somehow prioritize them but it was unsuccessful I would appreciate some help to somehow make the use of the memory cast constructor a last resort.

Here is my simplified code:

template<> struct PriorityTag<0> {};

template<typename T>
struct Comps {
   T X;
   T Y;
};

template<typename T>
class ConstructTest : Comps<T> {
public:
   ConstructTest(T x, T y) {
      this->X = x;
      this->Y = y;
   }

   template<typename U>
   ConstructTest(const Comps<U>& u, PriorityTag<4>) { //try to use this first
      this->X = u.X;
      this->Y = u.Y;
   }

   template<typename U>
   ConstructTest(const U& u, PriorityTag<0>) {
      *this = SomeMemoryCast<ConstructTest>(u); //use as a last resort
   }

   template<typename U>
   ConstructTest(const U& u) : ConstructTest(u, PriorityTag<4>()) {}
};

int main() {
   ConstructTest<int> testVal(5, 5);
   ConstructTest<float> copyed = testVal;
}```
obtuse spindleBOT
#

@opaque horizon

It looks like you may have code formatting errors in your message

Note: Make sure to use back-ticks (`) and not quotes (')
Note: Make sure to specify a highlighting language, e.g. `cpp`, after the back-ticks

Markup

```cpp
int main() {}
```

Result
int main() {}
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

fading hollow
#

reinterpret_cast<ConstructTest>(u) huh?

opaque horizon
#

well i wanted the constructor to cast any same sized type to this one but only if all other constructors fail i already made a SFINAE constraint for checking the size but if i try to cast a float to a int they are the same size so i cant do anything when that happens.

fading hollow
#

reinterpret_cast can only cast to a pointer or reference

opaque horizon
#

Sry my bad I had my own MemoryCast methode that uses a union to cast a type to another by its memory

fading hollow
#

Do you know there's std::bit_cast?

opaque horizon
#

yeah

opaque horizon
opaque horizon
#
template<typename T, typename U>
inline static T MemoryCast(const U& value) {
   union CastUnion {
      U input;
      T output;
      ~CastUnion() {
         input.~U();
      }
   };
   CastUnion u{};
   u.input = value;
   return u.output;
}

template<int Priority> struct PriorityTag : PriorityTag<Priority - 1> {};
template<> struct PriorityTag<0> {};

template<typename T>
struct Comps {
   T X;
   T Y;
};

template<typename T>
class ConstructTest : Comps<T> {
public:
   ConstructTest(T x, T y) {
      this->X = x;
      this->Y = y;
   }

   template<typename U>
   ConstructTest(const Comps<U>& u, PriorityTag<4>) { //try to use this first
      this->X = u.X;
      this->Y = u.Y;
   }

   template<typename U>
   ConstructTest(const U& u, PriorityTag<0>) {
      *this = MemoryCast<Comps<T>>(u);//use as a last resort
   }

   template<typename U>
   ConstructTest(const U& u) : ConstructTest(u, PriorityTag<4>()) {}
};

int main() {
   ConstructTest<int> testVal(5, 5);
   ConstructTest<float> copyed = testVal;
}```
hexed ginkgo
#

open cppreference/std::bit_cast and use their sample re-implementation

opaque horizon
#

okay, thanks that dose not matter in terms of this code, the problem is not with the casting method but with the ambiguity of the constructors I may fix the Memory cast problem but its out of scope of my question.

obtuse spindleBOT
#

@opaque horizon Has your question been resolved? If so, type !solved :)

opaque horizon
#

I forgot to mention I could have used concepts but My code should run in c++11 so I cant use them

finite walrus
#

because the version with const <Comps<U>& is more specialized/a better fit than const U&

opaque horizon
#

did u test that because I remember like it used the memory one and only uses The Comps one if i provide Comps as a input not a ConstructTest

#

the priority tag idea was just a attempt to solve the problem

finite walrus
#

;compile -std=c++20

#include <bit>
#include <iostream>

template<typename T>
struct Comps {
   T X;
   T Y;
};

template<typename T>
class ConstructTest : Comps<T> {
public:
   ConstructTest(T x, T y) {
      this->X = x;
      this->Y = y;
   }

   template<typename U>
   ConstructTest(const Comps<U>& u) { //try to use this first
      this->X = u.X;
      this->Y = u.Y;
      std::cout << __PRETTY_FUNCTION__ << std::endl;
   }

   template<typename U>
   ConstructTest(const U& u) {
      *this = std::bit_cast<Comps<T>>(u);//use as a last resort
      std::cout << __PRETTY_FUNCTION__ << std::endl;
   }
};

int main() {
   ConstructTest<int> testVal(5, 5);
   ConstructTest<float> copyed = testVal;
}
halcyon inletBOT
#
Program Output
ConstructTest<T>::ConstructTest(const Comps<U>&) [with U = float; T = float]
ConstructTest<T>::ConstructTest(const U&) [with U = ConstructTest<int>; T = float]
finite walrus
#

I misread the original code

finite walrus
#

you can deal with this in various ways but I'm somewhat reluctant to go through that because to a large extent this is plain annoying to write before concepts

#

you can sfinae your way out but that's really annoying with constructors

opaque horizon
#

i know but can you outline something in words at least I have some things that use sfinae so I might understand if you have an idea how to do it

hexed ginkgo
hexed ginkgo
fading hollow
hexed ginkgo
#

with C++11

opaque horizon
#

thats why i didn't want to provide the MemoryCast at first time dont worry about it i might fix it think of it as a std::bit_cast

#

just avoid thinking about it the important thing to consider is the constructors

hexed ginkgo
finite walrus
hexed ginkgo
#

in the compilation

finite walrus
#

you express a condition, and you can use enable_if if that's in c++11, otherwise you reimplement it

opaque horizon
#

I have TypeTrails implementations

finite walrus
#

iirc gcc is fairly annoying there, I've had to write some weird workaround because naming the class specialization would sometime trigger a hard error due to gcc trying to instantiate all constructor declarations, and my template constructor not being "dependent-enough" to gcc's tastes

#

might as well ask, but why do you not have access to the standard library

#

is it some free-standing thing where they kicked out a bunch of stuff

finite walrus
opaque horizon
#

its a header library that should work in non std projects like embedded and other projects like unreal

#

if i get a example in c++11 using std i can work with that. Its just the idea how to setup the sfinae to work here is the problem

fading hollow
#

I understand that this isn't what the question is about, but ugh

#

Are you sure there are no <type_traits> in unreal/embedded/etc

opaque horizon
#

yeah in ue5 there is not way to get type_traits working you are only able to use theirs.

#

it sucks I know cant really workaround that they need some fine control over memory or whatever but for now lets use std's type_traits and I make them independent after

#

I dont even know why I mentioned that i can't use std just act like i never said that

hexed ginkgo
#

so we don't really need that header

hexed ginkgo
opaque horizon
#

no unfortunately

hexed ginkgo
finite walrus
#

and is it required that it works magically for private inheritance?

finite walrus
#

even if you removed the magic memory conversion constructor, the other constructor is not eligible because of the private inheritance

#

if it has to be private inheritance, and the sample code has to work (excluding ambiguity issues) with the constructor taking a referene to the private base, then at minimum the template needs to be allowed to access the private members of other specializations

#

and you'd most likely need a constructor that takes in other specializations of ConstructTest

#

on top of the one taking Comps

#

but if you need to somehow make this work for anything that privately derives from Comps, there's something wrong in your setup

opaque horizon
#

no Comps should be or can be publicly accessible its my bad that i forgot to fix that

finite walrus
#

depending on your complete context it's more or less viable to use that setup

opaque horizon
#

okay I made some adjustments and cleared up what i need: so i need this code to work in c++11 and able to use std
the code works but uses the wrong constructor

#include <cstring>
#include <cstdio>

template<typename T>
struct Comps {
   T X;
   T Y;
};

template<typename T>
class ConstructTest : public Comps<T> {
public:
   ConstructTest(T x, T y) {
      this->X = x;
      this->Y = y;
   }

   template<typename U>
   ConstructTest(const Comps<U>& u) { //try to use this first
      this->X = (T)u.X;
      this->Y = (T)u.Y;
      printf("cast");
   }

   template<typename U> //use as a last resort
   ConstructTest(const U& u) {
      std::memcpy(this, &u, sizeof(*this));
      printf("memcpy");
   }
};

int main() {
   ConstructTest<int> testVal(5, 5);
   ConstructTest<float> copyed = testVal;
}```
finite walrus
#

the final catch all isn't great the way I wrote it because it's not actually a "catch all", it's selectively disabled to let the other overload go through

opaque horizon
#

oh this was one of my ideas thanks so much this might actually be perfect it maybe a bit complex it the end but his should work

finite walrus
#

mandatory complaint that you should prefer the member initializer list

opaque horizon
#

okay

obtuse spindleBOT
#

Thank you and let us know if you have any more questions!

This thread is now set to auto-hide after an hour of inactivity

hexed ginkgo
finite walrus
#

doesn't matter, the whole thing is scuffed