Visual Studio 2015无法编译有效代码(std函数错误?)

Gui*_*cot 6 c++ templates visual-c++ c++11 visual-studio-2015

我最近在c ++ 11中使用过一些代码.这段代码在GCC和Clang中运行良好,我在我的项目中广泛使用它.现在,我需要让它在MSVC中运行.我需要的所有c ++ 11功能都标记为是.但是,这个代码示例只是拒绝构建.我试图修复错误,但我还没有找到解决方案.这是样本:

#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;
}
Run Code Online (Sandbox Code Playgroud)

它应该输出这个:

My value is:5
My value is:9.5
My value is:9
My value is:9.4
Run Code Online (Sandbox Code Playgroud)

但相反,编译器输出向我抛出:

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 ==========
Run Code Online (Sandbox Code Playgroud)

这是完全相同的ideone代码,编译和执行成功:https://ideone.com/aANd04

提前致谢!

eca*_*mur 2

VS 2015(尚)不支持表达式 SFINAE,因此您无法std::is_constructiblestd::function. (请注意,严格来说,这是 C++14 功能;C++11std::function构造不支持 SFINAE。)

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

我们计划在 2015 RTM 后立即开始在编译器中实现表达式 SFINAE,并计划在 2015 年更新中提供它,支持生产使用。(但不一定是 2015 年更新 1。可能需要更长的时间。)