2013-02-08 5 views
3

В настоящее время у меня есть шаблон класса, который принимает ряд типов. Каждый тип, возможно, потребуется создать с классом. То, что я в настоящее время есть что-то вроде этого:Предотвращение ADL по параметрам шаблона

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?

+0

Рискуя быть очевидным, почему бы вам просто не определить TypeList и Placeholder? – rici

+1

Я не уверен, что это понимаю: * «MyClass заменит появление Placeholder собой, используйте полученные типы, и все хорошо». * Можете ли вы объяснить, что вы имеете в виду? Как вы можете заменить местозаполнитель в 'MyClass >' с полным типом, который относится к заполнителю? –

+0

@rici Определение или отсутствие определения TypeList не имеет никакого значения. Проблема с определением Placeholder заключается в том, что я определяю его? Некоторые шаблоны не будут работать с пустой структурой, и я бы хотел избежать зеркального отображения Заполнителя всего интерфейса MyClass. – rkjnsn

ответ

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; 

Обратите внимание на добавление ':: типа'

Наконец, в MyClass, Я заменил

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

с

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

дает мне тот же тип для InternalTypeList, как и прежде.

Поскольку зависимый тип Holder не имеет собственных параметров шаблона, компилятор не должен создавать экземпляры Placeholder для целей ADL, и все работает правильно.

Смежные вопросы