• Advertisement
Sign in to follow this  

C++ Polymorphic ECS | error C2385: ambiguous access of 'set'

Recommended Posts

Hi

I want to test out a polymorphic entity component system where the idea is that the components of an entity are "compositioned" using templated multiple inheritance. But I am running into an issue because I am stacking a bunch of methods with the same names inside a class (but they have different signatures). I want these methods to be overloaded by the template type but my compiler says the access is ambiguous. I have issues making them unambiguous with the using declaration because the paramter pack expansion causes a syntax error.

Can anyone here give me some advice on this?

 

template <class T>
class component
{
	T m_data;
protected:
	component() {};
	~component() {};
public:
	void set(const T& data) { m_data = data; };
};

template <class ...Ts>
class entity : public component<Ts>...
{
public:
	entity() {};
	~entity() {};
	//using component<Ts>::set...;		// syntax error
};

struct position { float x{}; float y{}; float z{}; };
struct velocity { float x{}; float y{}; float z{}; };

int main()
{
	entity<position, velocity> myEntity;

	position pos = { 1.0f, 1.0f, 1.0f };
	velocity vel = { 2.0f, 2.0f, 2.0f };

	myEntity.set(pos);		// error C2385: ambiguous access of 'set'
	//myEntity.set(vel);

	return 0;
}

 

Share this post


Link to post
Share on other sites
Advertisement

Bit of a sidebar, but I'm curious as to why are you trying to do this in the first place? First of all, this isn't actually ECS, because a fundamental aspect of ECS is that composition is done at run-time. What you have here is a complicated way to use multiple inheritance to make compile-time composition happen. The problems you're running into are one of the many reasons we don't generally use multiple inheritance. What does this approach give you over plain old composition (which we normally prefer over inheritance) or plain old multiple inheritance for that matter?

Edited by Oberon_Command

Share this post


Link to post
Share on other sites

For some reason the compiler cannot resolve which base class set() is to be called (someone more experienced might be able to shed light on the exact issues here).

The solution seems to be to do something like this:

template <class ...Ts>
class entity : public component<Ts>...
{
public:
    entity() {};
    ~entity() {};
  
    template <class U>
    void set(const U& data) { component<U>::set(data); }
};

 

Edited by TheComet

Share this post


Link to post
Share on other sites

The issue is that the compiler (By standard) may not resolve function overloads which reside in multiple templated bases, you need to explicitly define which base to search in as such:

template<typename T>
struct Base {
	void Foo(const T& value) {}
};

template<typename... T>
struct Front : public Base<T>... {
	template<typename U>
	void ExplicitFoo(const U& value) {
		Base<U>::Foo(value);
	}
};

int main() {
	Front<int, char> front;
  
	front.Foo(5);         // ERROR: Ambigous (but not really)
	front.ExplicitFoo(5); // OK
  
	return 0;
}

 

Edited by Migi0027

Share this post


Link to post
Share on other sites

Why would you inherit publicly from component<position> and component<velocity>? That code is telling me that your entity is a component<position> and it's also a component<velocity>, whatever those mean. I very much doubt public inheritance is the correct construct to use here.

 

Share this post


Link to post
Share on other sites

The example I gave is just a simplification to get to the issue, ambiguous access from multiple inheritance.

The component here is actually going to hold (or for that matter be) a proxy pointer to the data allocated somewhere else (in the system<T>).

Should the system move the data to another memory location this component will have its proxy pointer updated by the system. The proxy pointer is built from bi-directional smart pointers to ensure that a component get/set is only one indirection away, and should either the component be destructed or the data no longer be available in the system get/set and update proxy pointer will not crash the program.

With this I can create an entity and select its components using templates. I can also give it overloaded operators, such as, myEntity = pos1; and, myEntity = vel2;

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By Ward Correll
      I include the source code from what I am playing with. It's an exercise from Frank Luna's DirectX 12 book about rendering a skull from a text file. I get a stack overflow error and the program quits. I don't know where I went wrong it's messy programming on the parts I added but maybe one of you masterminds can tell me where I went wrong.
      Chapter_7_Drawing_in_Direct3D_Part_II.zip
    • By mister345
      Hi guys, so I have about 200 files isolated in their own folder [physics code] in my Visual Studio project that I never touch. They might as well be a separate library, I just keep em as source files in case I need to look at them or step through them, but I will never actually edit them, so there's no need to ever build them.
      However, when I need to rebuild the entire solution because I changed the other files, all of these 200 files get rebuilt too and it takes a really long time.
      If I click on their properties -> exclude from build, then rebuild, it's no good because then all the previous built objects get deleted automatically, so the build will fail.
      So how do I make the built versions of the 200+ files in the physics directory stay where they are so I never have to rebuild them, but
      do a normal rebuild for everything else? Any easy answers to this? The simpler the better, as I am a noob at Visual Studio settings. Thanks.
    • By Snaked
      Im working in this project for 1 year .... mostly i develop a tool and databases for make the different maps and now i'm doing the client for play the game
      Tell me if you like it......
      this is a capture of how is viewing atm

       
       
      https://youtu.be/9251v4wDTQ0
    • By reenigne
      For those that don't know me. I am the individual who's two videos are listed here under setup for https://wiki.libsdl.org/Tutorials
      I also run grhmedia.com where I host the projects and code for the tutorials I have online.
      Recently, I received a notice from youtube they will be implementing their new policy in protecting video content as of which I won't be monetized till I meat there required number of viewers and views each month.

      Frankly, I'm pretty sick of youtube. I put up a video and someone else learns from it and puts up another video and because of the way youtube does their placement they end up with more views.
      Even guys that clearly post false information such as one individual who said GLEW 2.0 was broken because he didn't know how to compile it. He in short didn't know how to modify the script he used because he didn't understand make files and how the requirements of the compiler and library changes needed some different flags.

      At the end of the month when they implement this I will take down the content and host on my own server purely and it will be a paid system and or patreon. 

      I get my videos may be a bit dry, I generally figure people are there to learn how to do something and I rather not waste their time. 
      I used to also help people for free even those coming from the other videos. That won't be the case any more. I used to just take anyone emails and work with them my email is posted on the site.

      I don't expect to get the required number of subscribers in that time or increased views. Even if I did well it wouldn't take care of each reoccurring month.
      I figure this is simpler and I don't plan on putting some sort of exorbitant fee for a monthly subscription or the like.
      I was thinking on the lines of a few dollars 1,2, and 3 and the larger subscription gets you assistance with the content in the tutorials if needed that month.
      Maybe another fee if it is related but not directly in the content. 
      The fees would serve to cut down on the number of people who ask for help and maybe encourage some of the people to actually pay attention to what is said rather than do their own thing. That actually turns out to be 90% of the issues. I spent 6 hours helping one individual last week I must have asked him 20 times did you do exactly like I said in the video even pointed directly to the section. When he finally sent me a copy of the what he entered I knew then and there he had not. I circled it and I pointed out that wasn't what I said to do in the video. I didn't tell him what was wrong and how I knew that way he would go back and actually follow what it said to do. He then reported it worked. Yea, no kidding following directions works. But hey isn't alone and well its part of the learning process.

      So the point of this isn't to be a gripe session. I'm just looking for a bit of feed back. Do you think the fees are unreasonable?
      Should I keep the youtube channel and do just the fees with patreon or do you think locking the content to my site and require a subscription is an idea.

      I'm just looking at the fact it is unrealistic to think youtube/google will actually get stuff right or that youtube viewers will actually bother to start looking for more accurate videos. 
    • By mister345
      Hi, can someone please explain why this is giving an assertion EyePosition!=0 exception?
       
      _lightBufferVS->viewMatrix = DirectX::XMMatrixLookAtLH(XMLoadFloat3(&_lightBufferVS->position), XMLoadFloat3(&_lookAt), XMLoadFloat3(&up));
      It looks like DirectX doesnt want the 2nd parameter to be a zero vector in the assertion, but I passed in a zero vector with this exact same code in another program and it ran just fine. (Here is the version of the code that worked - note XMLoadFloat3(&m_lookAt) parameter value is (0,0,0) at runtime - I debugged it - but it throws no exceptions.
          m_viewMatrix = DirectX::XMMatrixLookAtLH(XMLoadFloat3(&m_position), XMLoadFloat3(&m_lookAt), XMLoadFloat3(&up)); Here is the repo for the broken code (See LightClass) https://github.com/mister51213/DirectX11Engine/blob/master/DirectX11Engine/LightClass.cpp
      and here is the repo with the alternative version of the code that is working with a value of (0,0,0) for the second parameter.
      https://github.com/mister51213/DX11Port_SoftShadows/blob/master/Engine/lightclass.cpp
  • Advertisement