防止模板参数上的ADL

时间:2013-02-08 21:15:48

标签: c++ templates

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

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?

1 个答案:

答案 0 :(得分:0)

好的,我把一切都搞定了。诀窍是直接使用依赖类型而不是使用模板。我的最终解决方案是按如下方式定义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;

请注意添加&#39; :: type&#39;

最后,在MyClass中,我替换了

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

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

为我提供与InternalTypeList相同的类型。

因为依赖类型Holder没有它自己的模板参数,编译器不必为ADL目的实例化占位符类型,一切正常。