Skip to content

Conversation

@mwl4
Copy link
Contributor

@mwl4 mwl4 commented Feb 21, 2023

Consider following code:

#include "RmlUi/Core.h"

// client code, global namespace

template < typename T, typename ...Args >
inline std::unique_ptr< T > MakeUnique( Args &&...args )
{
    return ( std::unique_ptr< T >( new T( ::std::forward< Args >( args )... ) ) );
}

struct Invader
{
    Rml::String name;
};

void Foo( Rml::Context *context )
{
    if( Rml::DataModelConstructor constructor = context->CreateDataModel( "invaders" ) )
    {
        if( auto invader_handle = constructor.RegisterStruct<Invader>() )
        {
            invader_handle.RegisterMember( "name", &Invader::name );
        }
        // .........
    }
}

Compilation throws error:

2>rmlui\include\RmlUi\Core\DataStructHandle.h(154): error C2668: 'Rml::MakeUnique': ambiguous call to overloaded function
2>rmlui\include\RmlUi\Core\../Config/Config.h(189): note: could be 'std::unique_ptr<Rml::MemberObjectDefinition<Object,MemberType>,std::default_delete<Rml::MemberObjectDefinition<Object,MemberType>>> Rml::MakeUnique<Rml::MemberObjectDefinition<Object,MemberType>,Rml::VariableDefinition*&,MemberTypeInvader::* &>(Rml::VariableDefinition *&,MemberType Invader::* &)'
2>        with
2>        [
2>            Object=Invader,
2>            MemberType=Rml::String
2>        ]
2>XXXXX(59): note: or       'std::unique_ptr<Rml::MemberObjectDefinition<Object,MemberType>,std::default_delete<Rml::MemberObjectDefinition<Object,MemberType>>> MakeUnique<Rml::MemberObjectDefinition<Object,MemberType>,Rml::VariableDefinition*&,MemberTypeInvader::* &>(Rml::VariableDefinition *&,MemberType Invader::* &)' [found using argument-dependent lookup]
2>        with
2>        [
2>            Object=Invader,
2>            MemberType=Rml::String
2>        ]

The reason behind this is ADL (https://en.cppreference.com/w/cpp/language/adl)

template<typename Object>
template<typename MemberType>
bool StructHandle<Object>::CreateMemberObjectDefinition(const String& name, MemberType Object::* member_ptr)
{
// ....................................
	struct_definition->AddMember(
		name,
		MakeUnique<MemberObjectDefinition<Object, MemberType>>(underlying_definition, member_ptr)
	);

Notice, that member_ptr is passed as function argument to MakeUnique. Since Object template parameter is defined within global namespace, then there are two matching MakeUnique functions. One from Rml's Config.h file, and the user's one.

This PR should resolve this issue by forcing certain namespace.

@mikke89 mikke89 added the build Build system and compilation label Feb 22, 2023
@mikke89
Copy link
Owner

mikke89 commented Feb 22, 2023

Ah, thanks for the detailed PR. Makes sense to me, a subtle ADL strike.

@mikke89 mikke89 merged commit 4032c7f into mikke89:master Feb 22, 2023
@mwl4 mwl4 deleted the makeunique_fix branch February 23, 2023 10:49
@ShawnCZek
Copy link
Contributor

@mwl4
Copy link
Contributor Author

mwl4 commented Feb 27, 2023

@ShawnCZek I checked all MakeUniques along include header files and made fixes to them too.
#420

@mikke89 Review and merge it please.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

build Build system and compilation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants