c++ - 创建类的可变包装器

标签 c++ templates lambda c++11 g++

我有模板类 Reader

template<typename T>
class Reader{
    typedef T type;
};

特殊实现(派生类)具有带签名的方法

T read(IStream&,任意数量的参数,可能为零)

即类 IntegerReader 公共(public)函数:

template <typename T>
class IntegerReader : public Reader<T>{
public:
    T read(IStream& stream);
    T read(IStream& stream, T min, T max);
    T read(IStream& stream, T min, T max, std::string name);
}

现在我想创建一个包装器,它允许我创建另一个阅读器,并调用带有参数的阅读器。

我已经试过了:

template <typename T, typename... Args>
class ParametrizedReader : public Reader<typename T::type> {
    T reader;
    Args... args;
    ParametrizedReader(T reader, Args... args):reader(reader), args(args){
    }

    typename T::type read(IStream& stream){
        return reader.read(args..., stream);
    }
};
testlib/readerWrapper.hpp:7:6: error: expected unqualified-id before ‘...’ token
testlib/readerWrapper.hpp: In constructor ‘ParametrizedReader<T, Args>::ParametrizedReader(T, Args ...)’:
testlib/readerWrapper.hpp:8:61: error: class ‘ParametrizedReader<T, Args>’ does not have any field named ‘args’
testlib/readerWrapper.hpp: In member function ‘typename T::type ParametrizedReader<T, Args>::read(IStream&)’:
testlib/readerWrapper.hpp:12:22: error: ‘args’ was not declared in this scope

这个:

template <typename T, typename... Args>
class ParametrizedReader : public Reader<typename T::type> {
    std::function<T()> lambda;
    ParametrizedReader(T reader, Args... args){
        lambda = [=](IStream& stream){
            reader.read(stream, args...);
        };
    }

    typename T::type read(IStream& stream){
        return lambda(stream);
    }
};

testlib/readerWrapper.hpp:9:24: error: parameter packs not expanded with ‘...’:
testlib/readerWrapper.hpp:9:24: note:         ‘args’
testlib/readerWrapper.hpp:9:28: error: expansion pattern ‘args’ contains no argument packs

还有这个:

template <typename T, typename... Args>
class ParametrizedReader : public Reader<typename T::type> {
    std::function<T()> lambda;
    ParametrizedReader(T reader, Args... args){
        lambda = [reader, args...](IStream& stream){
            reader.read(stream, args...);
        };
    }

    typename T::type read(IStream& stream){
        return lambda(stream);
    }
};

testlib/readerWrapper.hpp:8:25: error: expected ‘,’ before ‘...’ token
testlib/readerWrapper.hpp:8:25: error: expected identifier before ‘...’ token
testlib/readerWrapper.hpp:8:28: error: parameter packs not expanded with ‘...’:
testlib/readerWrapper.hpp:8:28: note:         ‘args’

g++-4.7给出的编译错误

虽然我不确定第一个示例是否正确并且是否应该编译,但我相信第二个和第三个应该。

我找到了 this bug , 这似乎不是固定的。

是否有解决方法,我怎样才能做我想做的事?

最佳答案

您可以通过将参数绑定(bind)到 lambda 而不是捕获它们来解决此问题。

ParametrizedReader(T reader, Args... args){
    lambda = std::bind(
        [=](IStream& stream, Args... as){
            reader.read(stream, as...);
        }, args...);
}

虽然您可能想按照@Alexandre 所说的去做,而不是在确切的参数类型上参数化类模板:

template <typename T>
class ParametrizedReader : public Reader<typename T::type> {
    std::function<T()> lambda;
    template<typename... Args>
    ParametrizedReader(T reader, Args... args){
        lambda = std::bind(
            [=](IStream& stream, Args... as){
                reader.read(stream, as...);
            }, args...);
    }
    // ...
};

(注意:未经测试。)

也可能有效的是将 std::bind 放在第二个代码段中,然后像您的第二个或第三个解决方案一样尝试,这次使用可变函数模板。也许它有效,谁知道呢。

关于c++ - 创建类的可变包装器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12753651/

相关文章:

来自 MPEG 4 文件的 C++ Taglib 封面艺术

c++ - std::condition_variable::wait_until 如何工作

c++ - 为什么编译器认为这是一个函数?

c++ - 如何约束模板化 constexpr 递归函数输入参数

c++ - 如何使用 C++ 17 检查 operator != 是否存在模板参数?

c++ - 是否可以使用 std::pair 作为关联容器(如 std::map)的(唯一)模板参数?

c++ - 为什么我们不能使用 `std::multiset` 和自定义比较 lambda 作为 `std::map` 的值?

java - lambda表达式会自动为其入口参数创建新对象吗?

c++ - 如何为Windows Office 文档之类的文件添加属性?

c# - 如何检查 lambda 表达式中的日期是否为空,并仅在为空时才使用今天的日期