c++ - 防止模板参数上的 ADL

标签 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?

最佳答案

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

InternalTypeList 提供与之前相同的类型。

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

关于c++ - 防止模板参数上的 ADL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14781492/

相关文章:

c++ - 双重发送会产生 'hides virtual function'警告,为什么?

c++ - 将由 boost::variant 聚合的类型的对象传递给接受该 boost::variant 的函数

c++ - 添加 stringstream/cout 会损害性能,即使代码从未被调用

c++ - 具有模板模板参数的类模板特化

c++ - 使用命名空间中的模板调用模板模板方法时出现 False clang 错误

C++:模板成员函数,如 template<typename T> int foo<T>()

Windows 64 位 VectoredExceptionHandler 中的 C++ RTTI,MS Visual Studio 2015

c++ - Raspberry Pi 3,fann_create_standard 未定义

c++ - 根据 C++ 中的数据类型设置默认值

c++ - 为什么 "A<0>=0"中的模板 ID 由于大于或等于运算符 ">="而不能在没有空格的情况下编译?