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!
È interessante notare che il messaggio di errore non dice cosa sia '_Decayed'. È un tipo di tag? – dyp
Esplorerò l'intestazione msvc per vedere di cosa si tratta –
Forse @ stephan-t-lavavej può essere d'aiuto? –