9

为什么这段代码会编译?(用 g++ 和 clang++ 测试过)

以下代码用于接受函数并从中创建转发 std::function 的工厂方法。如您所见,内部的 lambda 接受const Arg&参数并将它们转发给给定的函数。

main()factory()用来创建一个转发器 to test_func(),它接受一个非常量引用参数。我不明白的是为什么这不会产生关于从参数中丢弃 const 限定符的错误。

请注意,确实在 中C创建的类的实例是在main()没有创建任何副本的情况下传递的。

#include <functional>
#include <iostream>

class C
{
public:
        C() {}

        C(const C&)
        {
                std::cout << "C copy\n";
        }
};

int test_func(C& cref)
{
        return 0;
}

template<typename Ret, typename... Arg>
std::function<Ret (const Arg&...)> factory(Ret (*func) (Arg...))
{
        return [ func ] (const Arg&... arg) -> Ret {
                return (func)(arg...);
        };
}

int main() {
        auto caller = factory(test_func);
        C c;
        caller(c);
        return 0;
}
4

1 回答 1

5

正如评论中提到的,您应该使用完美转发(请参阅 Scott Meyers 的关于Universal reference的演示文稿)。

在你的情况下,它应该是:

#include <functional>
#include <iostream>
#include <utility>

class C
{
public:
        C() {}

        C(const C&)
        {
                std::cout << "C copy\n";
        }
};

int test_func(const C& )
{
        return 0;
}

template<typename Ret, typename... Arg>
std::function<Ret (Arg...)> factory(Ret (*func) (Arg...))
{
        return [ func ] (Arg&&... arg) -> Ret {
                return func(std::forward<Arg>(arg)...);
        };
}

int main() {
        auto caller = factory(test_func);
        const C c;
        caller(c);
}

记下我在您的中更改C c;为的注释,并修改了 test_func。const C c;main()


如果您想避免创建副本,则必须确保 test_func 函数不按值获取。它应该通过引用(非常量的常量)。

于 2013-10-29T10:27:44.443 回答