2014-09-16 2 views
2

У меня есть следующий код:Шаблона с участием вложенных параметров шаблона и значения по умолчанию

#include <type_traits> 
#include <memory> 

class CDelegateCore {}; 

class CDelegate : public CDelegateCore {}; 

class CEvent 
{ 
    private: 

     /// Simple empty enumeration used for enable_if test. 
     enum class enabler_t {}; 

     template<typename T> 
     using EnableIf = typename std::enable_if<T::value, enabler_t>::type; 

    public: 

     CEvent() {} 
     ~CEvent() {} 

     void operator += (CDelegateCore* func) {} 

     template<typename T, typename Deleter, EnableIf<std::is_base_of<CDelegateCore, T>> = enabler_t{}> 
     void operator += (std::unique_ptr<T, Deleter> const& func) { *this += func.get(); } 
}; 

int main() 
{ 
    std::unique_ptr<CDelegate> testdel; 
    // ... initialize testdel ... 

    CEvent EVENT; 
    EVENT += testdel; 
} 

Цель здесь состоит в том, что когда у меня есть CDelegate принадлежащих к std::unique_ptr, что += перегрузки в CEvent использование std::enable_if будет вызывается, и параметры шаблона внутри std::unique_ptr будут выведены.

Этот код отлично работает в GCC и Clang, но в MSVC12 он не работает. Он не может решить эту функцию. Может ли кто-нибудь сказать мне, почему? У меня изначально не было аргумента шаблона для деблокирования unique_ptr, и он работал, но я не уверен, что на C++ есть правила относительно вывода типа с дефолтными параметрами вложенных шаблонов.

ответ

3

Я не уверен в этом, но я считаю, что это из-за отсутствия поддержки SFINAE выражения в VS2013. Вы можете получить код для работы на VS2013 (и НКУ и лязгом), если вы двигаетесь выражение enable_if к типу возвращаемого operator+=

template<typename T, typename Deleter> 
typename std::enable_if<std::is_base_of<CDelegateCore, T>::value>::type 
    operator += (std::unique_ptr<T, Deleter> const& func) { *this += func.get(); } 

Вы можете использовать свой EnableIf псевдоним, изменив второй аргумент шаблона для void, или просто используйте std::enable_if_t (требуется -std=c++1y на gcc и clang).

Live demo

+0

Я не смог найти документацию от Microsoft на отсутствие должной поддержки SFINAE. Где вы нашли свою информацию? –

+1

@ void.pointer [This] (http://blogs.msdn.com/b/vcblog/archive/2014/06/11/c-11-14-feature-tables-for-visual-studio-14-ctp1 .aspx) таблица не показывает VS2013 или VS14 поддержку выражения SFINAE. Но, как я уже говорил, я не уверен, что это эффект от этого. Я бы предположил, что выражение 'decltype' используется для SFINAE, чтобы не работать с VS2013, но не ваш пример. Возможно, остальная часть их поддержки SFINAE не является полной, или, по крайней мере, ошибкой. – Praetorian

0

VS2013 поддерживает SFINAE или, по крайней мере, большую часть из него. Изменить

template<typename T, typename Deleter, EnableIf<std::is_base_of<CDelegateCore, T>> = enabler_t{}> 

в

template<typename T, typename Deleter, class = EnableIf<std::is_base_of<CDelegateCore, T>>> 
+0

Что такое синтаксис class =? –

+0

Аргумент без аргумента с типом по умолчанию. – kozmo

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