从强类型的元组中创建一个PoD元组

时间:2018-03-27 19:59:45

标签: c++ c++11 tuples c++14 variadic-templates

我有一个StrongType<>类强制在PoD上强类型:

template <typename T, typename TAG>
class StrongType {
private:
    std::string mName;
    T mValue;
public:
    explicit StrongType(std::string n) : mName(n), mValue() {}
    explicit StrongType(std::string n, T v)
        : mName(n), mValue(std::move(v)) {
    }

    const T &value() const { return mValue; }
    std::string name() const { return mName; }
}; 

我有一个保持StrongType元组的类,需要返回一个非强类型的元组(实际上它应该调用一个非强类型参数的函数):

struct aTag {};
struct bTag {};
struct cTag {};

using aType = utils::StrongType<int, aTag>;
using bType = utils::StrongType<std::string, bTag>;
using cType = utils::StrongType<int, cTag>;

int main()
{
    aType a("a", 2);
    bType b("b", std::string {"b"});
    cType c("c", 10);

    AdvTuple<aType,bType,cType> t(a,b,c);

    //auto nt = t.getTuple();
    //std::cout << std::tuple_size<decltype(nt)>() << "\n";
    //std::cout << std::get<0>(nt) << "\n";

    //nt.call([](aType ra, bType rb, cType rc) {
    //});

    return 0;
}

这是我做的实现,但它没有编译:

#include <tuple>

template <typename ...T>
class AdvTuple {
private:
    std::tuple<T...> aTuple;
public:
    explicit AdvTuple(T... ts)
        : aTuple(std::make_tuple(ts...)) {
    }

    template <int i>
    decltype(std::get<i>(aTuple).value()) get() const {
        return std::get<i>(aTuple).value();
    }

    template <int N = 0, typename ...TA, std::enable_if<N < sizeof...(TA)> >
    auto getImpl(std::tuple<TA...> t) {
        return std::tuple_cat(std::make_tuple(std::get<N>(t)), getImpl<N+1>(t));
    };

    template <typename ...Q>
    std::tuple<Q...> getTuple() const {
        return getImpl<0>(aTuple);
    }
};

这是来自编译器的消息(mac上的clang):

 In file included from
 /Users/happycactus/Documents/Progetti/Experiments/tupletraits/main.cpp:3:
 /Users/happycactus/Documents/Progetti/Experiments/tupletraits/tupletypes.h:32:16: error: no matching member function for call to 'getImpl'
        return getImpl<0>(aTuple);
               ^~~~~~~~~~

 /Users/happycactus/Documents/Progetti/Experiments/tupletraits/main.cpp:25:17: note: in instantiation of function template specialization 'AdvTuple<utils::StrongType<int, aTag>, utils::StrongType<std::__1::basic_string<char>, bTag>, utils::StrongType<int, cTag> >::getTuple<>' requested here
    auto nt = t.getTuple();
              ^

 /Users/happycactus/Documents/Progetti/Experiments/tupletraits/tupletypes.h:26:10: note: candidate template ignored: couldn't infer template argument ''
    auto getImpl(std::tuple<TA...> t) {
         ^
 1 error generated.

1)如何解决?

2)如何使用推导出的PoD类型的call() / lambda实现function<>函数?即使非StrongTyped也可以。

我可以使用C ++ 11和14。

1 个答案:

答案 0 :(得分:1)

如果我理解你想要什么,你需要std::make_index_sequencestd::index_sequence

我的意思是...而不是递归getImpl(),您可以使用包扩展,如下所示

  template <std::size_t ... Is>
  auto getTuple (std::index_sequence<Is...> const &) const
   { return std::make_tuple(std::get<Is>(aTuple).value()...); }

  auto getTuple () const
   { return getTuple(std::make_index_sequence<sizeof...(T)>{}); }

您可以将private作为第一个getTuple()(收到std::index_sequence的那个)。

关于call(),我不清楚你想要什么。但我想你想要call() AdvTuple方法接收可调用的value()方法并用std::make_index_sequence调用它。

再次使用std::index_sequence / template <typename F, std::size_t ... Is> auto call (F f, std::index_sequence<Is...> const &) const { return f(std::get<Is>(aTuple).value()...); } template <typename F> auto call(F f) const { return call(f, std::make_index_sequence<sizeof...(Ts)>{}); } 技巧,

private

第一个可以是#include <tuple> #include <string> #include <iostream> #include <type_traits> template <typename T, typename> class StrongType { private: std::string mName; T mValue; public: explicit StrongType (std::string n) : mName{std::move(n)}, mValue{} { } template <typename U> explicit StrongType (std::string n, U v) : mName{std::move(n)}, mValue{std::forward<U>(v)} { } T const & value () const { return mValue; } std::string const & name () const { return mName; } }; template <typename ... Ts> class AdvTuple { private: std::tuple<Ts...> aTuple; template <std::size_t ... Is> auto getTuple (std::index_sequence<Is...> const &) const { return std::make_tuple(std::get<Is>(aTuple).value()...); } template <typename F, std::size_t ... Is> auto call (F f, std::index_sequence<Is...> const &) const { return f(std::get<Is>(aTuple).value()...); } public: template <typename ... Us> explicit AdvTuple (Us && ... us) : aTuple{std::make_tuple(std::forward<Us>(us)...)} { } template <std::size_t i> auto get() const { return std::get<i>(aTuple).value(); } auto getTuple () const { return getTuple(std::make_index_sequence<sizeof...(Ts)>{}); } template <typename F> auto call(F f) const { return call(f, std::make_index_sequence<sizeof...(Ts)>{}); } }; struct aTag {}; struct bTag {}; struct cTag {}; using aType = StrongType<int, aTag>; using bType = StrongType<std::string, bTag>; using cType = StrongType<int, cTag>; int main () { aType a("a", 2); bType b("b", std::string {"b"}); cType c("c", 10); AdvTuple<aType,bType,cType> t(a,b,c); auto nt = t.getTuple(); std::cout << std::tuple_size<decltype(nt)>() << "\n"; std::cout << std::get<0>(nt) << "\n"; t.call([](int, std::string, int){ std::cout << "Lambda!" << std::endl; }); return 0; }

以下是完整的C ++ 14编译示例

python myscript.py filename