2015-08-18 11 views
6

Recentemente ho lavorato con codice in C++ 11. Questo codice funziona perfettamente in GCC e Clang e l'ho ampiamente utilizzato in tutto il mio progetto. Ora, ho bisogno di farlo funzionare in MSVC. Tutte le funzionalità di C++ 11 di cui ho bisogno sono contrassegnate come sì. Tuttavia, questo esempio di codice semplicemente si rifiuta di costruire. Ho provato a correggere gli errori ma non ho ancora trovato una soluzione. Questo è il campione:Il codice valido non viene compilato da Visual Studio 2015 (bug della funzione std?)

#include <functional> 
#include <iostream> 
#include <type_traits> 

template<typename T> 
struct Provider final { 
    Provider() = delete; 
    Provider(const Provider& other) : _callback{ other._callback } {} 
    Provider(Provider&& other) : _callback{ std::move(other._callback) } {} 

    Provider& operator=(Provider&& other) { 
     std::swap(other._callback, _callback); 
     return *this; 
    } 

    Provider& operator=(const Provider& other) { 
     _callback = other._callback; 
     return *this; 
    } 

    template<typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type, typename = typename std::enable_if<!std::is_same<U, T>::value>::type> 
    Provider<T>& operator=(Provider<U>&& other) { 
     std::swap(other._callback, _callback); 
     return *this; 
    } 

    template<typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type, typename = typename std::enable_if<!std::is_same<U, T>::value>::type> 
    Provider<T>& operator=(const Provider<U>& other) { 
     _callback = other._callback; 
     return *this; 
    } 

    template<typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type, typename = typename std::enable_if<!std::is_same<U, T>::value>::type> 
    Provider(const Provider<U>& other) : _callback{ other._callback } {} 

    template<typename U, typename = typename std::enable_if<std::is_convertible<U, T>::value>::type, typename = typename std::enable_if<!std::is_same<U, T>::value>::type> 
    Provider(Provider<U>&& other) : _callback{ std::move(other._callback) } {} 

    template<typename U, typename = typename std::enable_if<std::is_constructible<std::function<T()>, U>::value>::type> 
    Provider(U callback) : _callback{ callback } {} 

    template<typename = typename std::enable_if<!std::is_constructible<std::function<T()>, T>::value, T>::type> 
    Provider(T value) : _callback{[=] { return value; }} {} 

    template<typename U> 
    friend struct Provider; 

    T operator()() const { 
     return _callback(); 
    } 

private: 
    std::function<T()> _callback; 
}; 

template<typename T> 
void doSomething(Provider<T> p) { 
    std::cout << "My value is:" << p() << std::endl; 
} 

int main() 
{ 
    Provider<int> p1 = 9; 
    Provider<double> p2 = [] { return 9.4; }; 
    Provider<unsigned int> p3{9}; 
    Provider<float> p4{[]{ return 9.4f; }}; 

    doSomething<unsigned int>(5); 
    doSomething<float>([] { return 9.5f; }); 
    doSomething<int>(p1); 
    doSomething<double>(p2); 

    return 0; 
} 

Si suppone che in uscita questo:

My value is:5 
My value is:9.5 
My value is:9 
My value is:9.4 

Ma invece, l'output del compilatore lanciare questo a me:

1>------ Build started: Project: test1, Configuration: Debug Win32 ------ 
1> test1.cpp 
1>c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1501): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Types &&...)' 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1501): note: With the following template arguments: 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1501): note: '_Callable=_Decayed &' 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\type_traits(1501): note: '_Types={}' 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(210): note: see reference to function template instantiation '_Rx std::_Invoke_ret<_Rx,_Callable&>(std::_Forced<_Rx,false>,_Callable &)' being compiled 
1>   with 
1>   [ 
1>    _Rx=unsigned int, 
1>    _Callable=_Decayed 
1>   ] 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(208): note: while compiling class template member function 'unsigned int std::_Func_impl<_Decayed,_Alloc,_Ret>::_Do_call(void)' 
1>   with 
1>   [ 
1>    _Alloc=std::allocator<int>, 
1>    _Ret=unsigned int 
1>   ] 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(136): note: see reference to class template instantiation 'std::_Func_impl<_Decayed,_Alloc,_Ret>' being compiled 
1>   with 
1>   [ 
1>    _Alloc=std::allocator<int>, 
1>    _Ret=unsigned int 
1>   ] 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(339): note: see reference to class template instantiation 'std::_Is_large<_Myimpl>' being compiled 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(318): note: see reference to function template instantiation 'void std::_Func_class<_Ret>::_Reset_alloc<_Ty,std::allocator<_Ty>>(_Fx &&,const _Alloc &)' being compiled 
1>   with 
1>   [ 
1>    _Ret=unsigned int, 
1>    _Ty=int, 
1>    _Fx=int, 
1>    _Alloc=std::allocator<int> 
1>   ] 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(318): note: see reference to function template instantiation 'void std::_Func_class<_Ret>::_Reset_alloc<_Ty,std::allocator<_Ty>>(_Fx &&,const _Alloc &)' being compiled 
1>   with 
1>   [ 
1>    _Ret=unsigned int, 
1>    _Ty=int, 
1>    _Fx=int, 
1>    _Alloc=std::allocator<int> 
1>   ] 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(484): note: see reference to function template instantiation 'void std::_Func_class<_Ret>::_Reset<int>(_Fx &&)' being compiled 
1>   with 
1>   [ 
1>    _Ret=unsigned int, 
1>    _Fx=int 
1>   ] 
1> c:\program files (x86)\microsoft visual studio 14.0\vc\include\functional(484): note: see reference to function template instantiation 'void std::_Func_class<_Ret>::_Reset<int>(_Fx &&)' being compiled 
1>   with 
1>   [ 
1>    _Ret=unsigned int, 
1>    _Fx=int 
1>   ] 
1> c:\users\master\documents\visual studio 2015\projects\test1\test1\test1.cpp(43): note: see reference to function template instantiation 'std::function<T (void)>::function<U>(_Fx)' being compiled 
1>   with 
1>   [ 
1>    T=unsigned int, 
1>    U=int, 
1>    _Fx=int 
1>   ] 
1> c:\users\master\documents\visual studio 2015\projects\test1\test1\test1.cpp(43): note: see reference to function template instantiation 'std::function<T (void)>::function<U>(_Fx)' being compiled 
1>   with 
1>   [ 
1>    T=unsigned int, 
1>    U=int, 
1>    _Fx=int 
1>   ] 
1> c:\users\master\documents\visual studio 2015\projects\test1\test1\test1.cpp(68): note: see reference to function template instantiation 'Provider<unsigned int>::Provider<int,void>(U)' being compiled 
1>   with 
1>   [ 
1>    U=int 
1>   ] 
1> c:\users\master\documents\visual studio 2015\projects\test1\test1\test1.cpp(68): note: see reference to function template instantiation 'Provider<unsigned int>::Provider<int,void>(U)' being compiled 
1>   with 
1>   [ 
1>    U=int 
1>   ] 
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ========== 

Questo è lo stesso codice esatto su ideone, compilazione ed esecuzione: https://ideone.com/aANd04

Grazie in anticipo!

+0

È interessante notare che il messaggio di errore non dice cosa sia '_Decayed'. È un tipo di tag? – dyp

+0

Esplorerò l'intestazione msvc per vedere di cosa si tratta –

+0

Forse @ stephan-t-lavavej può essere d'aiuto? –

risposta

2

VS 2015 non supporta (ancora) l'espressione SFINAE, quindi non è possibile utilizzare std::is_constructible su std::function. (Si noti che questo è in senso stretto una funzione C++ 14; C++ 11 std::function costruzione non è SFINAE-enabled.)

Da http://blogs.msdn.com/b/vcblog/archive/2015/04/29/c-11-14-17-features-in-vs-2015-rc.aspx:

Stiamo progettando di avviare l'attuazione Expression SFINAE in il compilatore immediatamente dopo il 2015 RTM e stiamo pianificando di consegnarlo in un aggiornamento al 2015, supportato per l'uso di produzione. (Ma non necessariamente 2015 Aggiornamento 1. Potrebbe volerci più tempo.)

+0

Grazie mille. Mi aspetto di trasferire il mio codice in Visual Studio non appena implementeranno questa funzione. –

Problemi correlati