c++ - 具有段错误的函数模板

标签 c++ c++11 c++14

我写拉函数来链接(读取->通过...->接收器)

template<typename T>
auto pull(T &&stream) {
    return std::forward<T>(stream);
}

// return void/read
// read -> sink
// read -> through
template<typename R, typename S>
auto pull(R &&read, S &sink) {
    return sink(std::forward<R>(read));
}

// return read
// read -> through -> ...
template<typename R, typename T, typename... Ts>
auto pull(R &&read, T &through, Ts &&... args) {
    return pull(through(std::forward<R>(read)), std::forward<Ts>(args)...);
}

read 函数,像这样,提供一个 vector :
template<typename T>
auto values(T &begin, T &end) {
    return [&](bool abort, auto cb) {

        if (end != begin) {
            cb(false, *begin++);
        } else {
            cb(true, *begin);
        }
    };
}

通过函数,像这样:
template<typename T, typename M>
auto Map(M &&mapper) {

    return [&](auto &&read) {
        return [&](bool abort, auto cb) {
            read(abort, [&](bool end, T val) {
                if (end)
                    cb(true, val);
                else
                    cb(false, mapper(val));
            });
        };
    };
}

像这样的接收器功能:
template<typename T, typename R>
auto log(R &&read) {

    std::function<void(bool, T)> more = [&](bool done, T val) {
        if (!done) {
            cout << val << endl;
            read(false, more);
        }
    };

    read(false, more);
}

然后在主函数中:
int main() {
    vector<int> vec;
    for (int i = 1; i < 4; i++) {
        vec.push_back(i);
    }
    auto begin = vec.begin();
    auto end = vec.end();

    auto vals = values(begin, end);
    auto mapper = [&](int val) { return val * 2; };
    auto timesTwo = Map<int>(mapper);
    auto newVals1 = pull(vals, timesTwo, timesTwo);
    auto newVals2 = pull(vals, timesTwo);
    auto logInt = [&](auto read) { log<int>(read); };

    //pull(newVals1, logInt); // Segmentation fault, how to correct `pull` function to make this run right
    pull(newVals2, logInt); // ok

    return 0;
}
pull(newVals2, logInt);工作正常,

但是 pull(newVals1, logInt);Segmentation fault ;

我想做pull(newVals1, logInt);工作正常。

我认为,可能是 pull 中的一些错误功能,但我不知道在哪里,谁可以帮助我?

code example

最佳答案

我想我已经弄清楚了哪里出了问题。正如之前的用户评论的那样,在通过引用捕获超出其范围的 lambda 时,您需要非常谨慎。

具体来说,我认为问题出在 Map 内部。函数,其中内部 lambda 捕获 read通过引用论证。如果它使用左值参数调用,其作用域将超过 lambda,这很好,就像在单个调用案例 pull(vals, timesTwo) 中的情况一样。 => timesTwo(vals) , 但在双重调用情况下 pull(vals, timesTwo, timesTwo) => timesTwo(timesTwo(vals)) , 参数被传递给 timesTwo 的外部调用是一个右值,所以 read引用对象立即悬空。

另一个不相关的问题:在 values函数,else lambda 中的子句将取消引用结束迭代器。我不相信你依赖它的返回值,它似乎按预期工作,但它是未定义的行为。

关于c++ - 具有段错误的函数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59950494/

相关文章:

c++ - std::is_default_constructible 具有私有(private)访问和友元函数

成员的 C++11 decltype

c++ - klee on c++14 程序

c++ - 非标准基础中的算术

c++ - C++中的Strcpy不起作用

c++ - O(NlogN) 或 O(Nlog^2N) 中坐标值的 LIS

c++ - 当操作数类型为 short 时编译模板标量 vector 加法运算符失败

visual-studio - 具有两个相同类型的自动参数的 MSVC lambda

c++ - 在 C++ 中使用 stringstream 和一个 int 变量来验证输入是一个 int

c++ - 如何修复 "SDL_image could not initialize!"?