防止模板参数上的ADL

Prevent ADL on template parameters

本文关键字:ADL 参数      更新时间:2023-10-16

我目前有一个类模板,它采用了一系列类型。每个类型可能都需要用类本身进行实例化。我目前拥有的是这样的东西:

template <typename... Types>
struct TypeList; // Not defined
struct Placeholder; // Not defined
template <typename Types, typename AnotherType = Default>
class MyClass
{
    // ...
};

然后你可以这样使用它:

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

MyClass将用它自己替换Placeholder的外观,使用生成的类型,一切都很好。

当我尝试做以下任何一种事情时,问题就会出现:

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

这两种情况都会导致编译器错误,因为编译器试图实例化Container1<Placeholder>Container2<std::string, Placeholder>以执行参数相关查找(ADL),而Placeholder本身的实例化失败。

我知道可以通过做例如来避免ADL

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

然而,我不想让MyClass的用户不断抑制ADL。有没有其他直接的方法让用户提供一个类型列表,而不将这些类型用于ADL?

好吧,一切都好了。诀窍是使用依赖类型,而不是直接使用模板。我的最终解决方案是将TypeList定义如下:

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;
};

然后,MyClass的用户可以进行

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

注意添加了"::type"

最后,在MyClass中,我替换了

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

带有

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

给了我与以前相同的CCD_ 7类型。

因为依赖类型Holder没有自己的模板参数,所以编译器不必为了ADL的目的实例化占位符类型,并且一切都正常工作。