2015-02-22 1 views
3

У меня есть группа классов, которые имеют один или несколько членов типа memberA, memberB, memberC. Не у всех классов есть все участники. Я хочу создать шаблон, который будет устанавливать член, такие какпроверка экземпляра шаблона для члена, существующего в классе

template <typename T> 
void setAttributes(t & myClass, typeA memA, typeB memB, typeC memC) 
{ 
    myClass.memberA = memA; 
    myClass.memberB = memb; 
    myClass.memberC = memC; 
} 

Очевидно, что это произойдет сбой во время компиляции при попытке создать экземпляр класса, который отсутствует один из членов. Есть ли #if или нечто подобное, что позволит проверить, чтобы сделать для условной компиляции формы

не имеют доступа прямо сейчас на самом деле попробовать это или что-нибудь подобное, и я хотел бы знать, если есть правильный способ его настройки.

Я видел ссылки на SFINAE («сбой замены» не является ошибкой.)), Но я не уверен, как он будет использоваться в этом случае. Правильно ли это предложение?

Substitution failure is not an error Пример, казалось бы, подразумевает, что я должен создать отдельную функцию для каждого элемента с дублирующейся функцией без этого члена.

template <typename T> 
void setMemberA(T & myClass, typeA memA) 
{ 
    myClass.memberA = memA; 
} 

template <typenum T> 
void setMemberA(T & myClass) 
{ 
    // This is a dummy template to avoid a compilation problem 
} 
+0

Возможно, вы захотите использовать SFINAE. – user4098326

+0

@ user4098326 Я видел ссылки на это, но не смог экстраполировать из примеров, приведенных в моем случае. – sabbahillel

ответ

3

Вот возможный set_memberA_if_exists реализация:

namespace details { 
    template<class T> 
    auto set_memberA_if_exists_impl(T & myClass, typeA memA, int) 
     -> decltype(myClass.memberA = memA, void()) { 
     myClass.memberA = memA; 
    } 

    template<class T> 
    void set_memberA_if_exists_impl(T & myClass, typeA memA, long) {} 
} 

template<class T> 
void set_memberA_if_exists(T & myClass, typeA memA) { 
    details::set_memberA_if_exists_impl(myClass, memA, 0); 
} 

Объяснение:

SFINAE относится только к подписи, а не тело, шаблона функции, поэтому хитрость заключается в том, чтобы закодировать чек внутри сигнатуры шаблона функции. Это легко использовать с возвращаемым типом возврата C++ 11 - -> decltype(myClass.memberA = memA, void()). Если выражение myClass.memberA = memA не будет компилироваться, оно вызывает сбой замены и удаляет шаблон функции из набора перегрузки. Так что вызов set_memberA_if_exists_impl все равно будет компилироваться в этом случае, мы также обеспечим еще одну перезагрузку do-nothing.

Нам также нужен способ различать эти две перегрузки, когда они являются жизнеспособными. Это делается путем введения третьего параметра. Тип третьего параметра do-something overload - int, а перегрузка do-nothing - long. Предоставляя 0 (int) в качестве третьего аргумента, когда мы его вызываем, мы гарантируем, что перегрузка «что-то» является предпочтительной, когда она жизнеспособна.

+0

очень умный, +1. SFINAE занимает места в 'decltype', правильно? И ',' является хорошим старым оператором запятой, который вы использовали только для того, чтобы оценить первое выражение 'myClass.memberA = memA', это правильно? – vsoftco

+0

@vsoftco Довольно много. –

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

  • Нет связанных вопросов^_^