11

我有这个代码:

#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 传递函子对象,以避免无用的复制 costructor 调用。我期望以下输出:

F: 6
7

它可以与 GCC >= 4.4.0、Visual Studio 2008 以及通过将 std::tr1 命名空间替换为 boost 来正常工作。它仅不适用于新的 Visual Studio 2010 Express Beta 2 和 Release Candidate。

这个新的 C++ 功能在 vs2010 中是否存在错误?还是代码中有一些错误或误用?

4

2 回答 2

11

我想我找到了原因。这就是 TR13.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(无参数),则类型为 void。
    • 如果 N>0,则类型为typename F::template result<F(T1, T2,..., TN)>::type

错误消息是尝试这些回退的人工制品。result_type为to提供一个 typedef int,我认为它应该可以工作。请注意,在 中C++0x,这是不同的。它不依赖于result_type模板result,因为它可以使用decltype.

如果<functional>它在 C++0x 模式下使用 MSVC10 失败,我会说,它闻起来像一个错误。但也许其他人知道发生了什么。<tr1/functional>如果该标头选择采用decltype方式而不是::result_type. 我会 typedef result_type- 这样我认为无论tr1是使用标题还是c++0x标题,它都应该始终有效。


另请注意,boost::tr1在其文档中说它不支持函数调用运算符(但它仅支持隐式转换为T&)。

于 2010-03-11T13:46:17.887 回答
1

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

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

于 2010-03-11T14:12:22.077 回答