I've been working with some code recently in c++11. This code is working fine in GCC and Clang, and I've used it extensively all across my project. Now, I need to make it work in MSVC. All the c++11 features I need are marked as yes. However, this sample of code simply refuses to build. I tried to fix errors but I did not found a solution yet. This is the sample:
#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;
}
It is supposed to output this:
My value is:5
My value is:9.5
My value is:9
My value is:9.4
But instead, the compiler output throw this at 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 ==========
This is the exact same code on ideone, compiling and executing successfully: https://ideone.com/aANd04
Thanks in advance!
VS 2015 does not (yet) support expression SFINAE, so you can't use std::is_constructible
on std::function
. (Note that this is strictly speaking a C++14 feature; C++11 std::function
construction is not SFINAE-enabled.)
From http://blogs.msdn.com/b/vcblog/archive/2015/04/29/c-11-14-17-features-in-vs-2015-rc.aspx:
We're planning to start implementing Expression SFINAE in the compiler immediately after 2015 RTM, and we're planning to deliver it in an Update to 2015, supported for production use. (But not necessarily 2015 Update 1. It might take longer.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With