2010-07-09 3 views
4

После довольно долгого времени отладки моего кода, я разыскал причину моих проблем в некоторые результатах неожиданного шаблона специализации с использованием enable_if:Странного поведения enable_if с помощью вложенных классов (? MSVC компилятора ошибки или функции)

Следующий код не утверждение в DoTest() в Visual Studio 2010 (и 2008), в то время как оно не в g ++ 3.4.5. Однако, когда я удаляю шаблон с SomeClass или переместим my_condition из области SomeClass он также работает в MSVC.

Есть ли что-то не так с этим кодом, что бы объяснить это поведение (по крайней мере частично) или это ошибка в компиляторе MSVC?

(используя этот пример кода, это то же самое для усиления и C++ 0x СТЛ версии)

#include <cassert> 
#include <boost\utility\enable_if.hpp> 

template <class X> 
class SomeClass { 
public: 
    template <class T> 
    struct my_condition { 
     static const bool value = true; 
    }; 

    template <class T, class Enable = void> 
    struct enable_if_tester { 
     bool operator()() { return false; } 
    }; 

    template <class T> 
    struct enable_if_tester<T, typename boost::enable_if< my_condition<T> >::type> { 
     bool operator()() { return true; } 
    }; 

    template <class T> 
    void DoTest() { 
     enable_if_tester<T> test; 
     assert(test()); 
    } 
}; 

int main() { 
    SomeClass<float>().DoTest<int>(); 
    return 0; 
} 

При попытке исправить это, перемещая условие из сферы, я также заметил, что это не достаточно, даже при использовании зОго :: enable_if, но, по крайней мере, он работает с буст :: enable_if:

#include <cassert> 
//#include <boost\utility\enable_if.hpp> 
#include <type_traits> 

template <class T, class X> 
struct my_condition { 
    static const bool value = true; 
}; 

template <class X> 
class SomeClass { 
public: 
    template <class T, class Enable = void> 
    struct enable_if_tester { 
     bool operator()() { return false; } 
    }; 

    template <class T> 
    //struct enable_if_tester<T, typename boost::enable_if< my_condition<T, X> >::type> { 
    struct enable_if_tester<T, typename std::enable_if< my_condition<T, X>::value >::type> { 
     bool operator()() { return true; } 
    }; 

    template <class T> 
    void DoTest() { 
     enable_if_tester<T> test; 
     assert(test()); 
    } 
}; 

int main() { 
    SomeClass<float>().DoTest<int>(); 
    return 0; 
} 

Я надеюсь, что кто-то объяснение этому.

+0

Не удалось распечатать сообщение об ошибке из компилятора? Или это только утверждение неудачи? – doc

+0

Из любопытства есть ли конкретная причина, по которой enable_if_tester должен быть структурой, а не методом? – Staffan

+1

@ Стаффан: Частичная специализация. –

ответ

4

Все в порядке с вашим кодом, это просто, что VC глючит. Известно, что у него проблемы с частичной специализией шаблонов классов-членов шаблона.

+0

Спасибо, я действительно не ожидал такой ошибки в последнем VS. Я предполагаю, что сейчас поставлю некоторые статические утверждения в специализации, чтобы проверить условие проверки, поэтому я замечаю, когда компилятор немедленно исчез. Однако надежное обходное решение, которое гарантирует, что компилятор сделает то, что ожидается, будет приятнее. – mfya