问题 Visual Studio 2010和std :: function


我有这个代码:

#include <iostream>
#include <functional>

struct A
{
    int operator()(int i) const {
        std::cout << "F: " << i << std::endl;
        return i + 1;
    }
};

int main()
{
    A a;
    std::tr1::function<int(int)> f = std::tr1::ref(a);
    std::cout << f(6) << std::endl;
}

目的是通过reference_wrapper传递functor对象,以避免无用的复制costructor调用。 我期待以下输出:

F: 6
7

它适用于GCC> = 4.4.0,Visual Studio 2008,并通过用boost替换std :: tr1命名空间来提升。它仅适用于新的Visual Studio 2010 Express Beta 2和Release Candidate。

这个新的C ++功能在vs2010中有漏洞吗? 或者代码中有一些错误或误用?


10399
2018-03-11 13:35


起源

它怎么行不通? - UncleBens
@litb:我认为OP在使用时遇到了问题 std::tr1::ref 模板类和 不 提升VS2010。 - dirkgently
这是vs2010的构建输出: pastebin.com/YQf4Qe8W - Dj Gaspa
更多细节:包含<boost / tr1 / functional.hpp>而不是<functional>的相同代码适用于vs2008,但钢不适用于vs2010。 Tha内置实现的vs2010的<funtcional>头(及其deps)似乎支持reference_wrapper对象的函数调用...但它无法编译:( - Dj Gaspa


答案:


我想我找到了原因。这就是TR1 3.4/2 说的 result_of<T(A1, A2, ..., AN)>::type,用于确定返回类型 reference_wrapper<T>::operator()

实现可以通过任何方式确定类型成员,该方法产生给定类型的表达式f(t1,t2,...,tN)的确切类型。 [注意:目的是允许实现使用特殊的编译器钩子 - 结束注意]

然后第3段:

如果F不是标准库定义的函数对象,并且如果实现无法确定表达式f(t1,t2,...,tN)的类型或表达式是否格式错误,则实现应使用以下过程确定类型成员:

  • 如果F是一个可能是cv限定的类类型,没有名为的成员 result_type 或者如果 typename F::result_type 不是一种类型:      
    • 如果N = 0(无参数),则type为void。
    • 如果N> 0,则键入 typename F::template result<F(T1, T2,..., TN)>::type

错误消息是尝试这些后备的人工制品。提供typedef result_type 至 int 我认为它应该有效。注意在 C++0x,这是不同的。它不依赖 result_type 或者a result 模板,因为它可以使用 decltype

如果有 <functional> 它会在C ++ 0x模式下以MSVC10失败,它会闻起来像一个bug,我会说。但也许别人知道发生了什么。它可能(但不保证)可以使用 <tr1/functional> 在C ++ 0x模式下,如果该标头选择采取 decltype 方式而不是 ::result_type。我会打字 result_type  - 这种方式我认为它应该始终有效,无论是否 tr1 使用标头或 c++0x 头。


还要注意 boost::tr1 在它的文档中说它不支持函数调用操作符(但它只支持隐式转换) T&)。


11
2018-03-11 13:46



是的,这解决了问题:D对于vs2010而言,对于之前的2008版本的回归是很可惜的...最近的草稿严格要求编译器能够自动识别返回类型。 open-std.org/JTC1/SC22/WG21/docs/papers/2009/n3000.pdf 第20.7.4段 - Dj Gaspa


我在这里遇到类似的问题: 防止不必要的C ++仿函数对象副本

为了使它在MSVC10上编译,我必须从std :: unary_function派生我的函数对象。


1
2018-03-11 14:12