Prevent ADL by template parameters

I currently have a class template that accepts a number of types. Each type might need to be created with a class. I currently have something like this:

template <typename... Types>
struct TypeList; // Not defined

struct Placeholder; // Not defined

template <typename Types, typename AnotherType = Default>
class MyClass
{
    // ...
};

      

Then you can use it like this:

typedef MyClass<TypeList<Container1<Placeholder>, Container2<std::string,
        Placeholder>, OtherType>, OptionalType> MyTypedef;
MyTypedef my_object;

      

MyClass

replace the look and feel Placeholder

with itself, use the result types and you should be fine.

The problem comes up when I try to do something like any of these:

MyTypedef *my_ptr = &my_object;
my_free_function(my_object);

      

Both of them throw a compiler error because the compiler is trying to instantiate Container1<Placeholder>

and Container2<std::string, Placeholder>

search for dependent arguments (ADL), and that instance itself Placeholder

fails.

I know ADL can be avoided, for example

MyTypedef *my_ptr = std::addressof(my_object);
(my_free_function)(my_object);

      

However, I don't want to burden the user with the MyClass

need to suppress ADL all the time. Is there another easy way to provide the user with a list of types not used for ADL?

+3


source to share


1 answer


Okay, everything works for me. The trick was to use the dependent type directly, rather than use a template. My final solution was to define the TypeList like this:

template <typename... Types>
struct TypeList
{
private:
    struct Holder
    {
    private:
        typedef TypeList<Types...> InnerTypeList;
        template <typename Types, typename AnotherType>
        friend class MyClass;
    };
public:
    typedef Holder type;
};

      

Then MyClass users can do

typedef MyClass<TypeList<Container1<Placeholder>, Container2<std::string,
        Placeholder>::type, OtherType>, OptionalType> MyTypedef;
MyTypedef my_object;

      

Notice the addition of ':: type'

Finally, in MyClass, I replaced



typedef typename SubstituteType<Types, Placeholder, MyClass>::type InternalTypeList;

      

from

typedef typename SubstituteType<Types::InnerTypeList, Placeholder, MyClass>::type
        InternalTypeList;

      

gives me the same type for InternalTypeList

as before.

Since the dependent type Holder

has no template parameters of its own, the compiler does not need to create Placeholder instances for ADL targets, and everything works as expected.

0


source







All Articles