简体   繁体   English

我可以从向量数组初始化一个 std::tuple 吗?

[英]can I initialize an std::tuple from a vector array?

I have an std::vector containing a variant class.我有一个包含变体类的 std::vector。 I want to construct a tuple with the same data.我想用相同的数据构造一个元组。 Is this possible?这可能吗? The normal construction methods for a tuple seem quite restrictive.元组的正常构造方法似乎非常严格。

                    //In reality, I'm using JUCE::var.
                    // SimpleVariant is here just to make the example code more explicit.
struct SimpleVariant
{
    SimpleVariant(int i) :                a(i), b("") {}
    SimpleVariant(const std::string& s) : a(0), b(s) {}

    operator int() const { return a; }
    operator std::string() const { return b; }

private:
    int a;
    std::string b;
};


template <typename... T>
struct VariantTuple
{
    VariantTuple(const std::vector<SimpleVariant>& v)
    {
        // how do I initialize the tuple here?
    }

private:
    std::tuple<T...> tuple;
};


        std::vector<SimpleVariant> v{ SimpleVariant(1),
                                      SimpleVariant(2),
                                      SimpleVariant("a") };

        VariantTuple<int, int, std::string> t (v);

Some clarifications based on the comments:基于评论的一些澄清:

I do not need the tuple to match the array term by term, or to deduce the types from the given array.我不需要元组来逐项匹配数组,或者从给定的数组中推断出类型。 I want to take a given array and then extract Variants that match a certain type.我想获取一个给定的数组,然后提取与某种类型匹配的 Variants。 So, for instance, given the above array v , I would like to be able to construct a VariantTuple<int, std::string> , and have it match the terms "1" and "a".因此,例如,给定上述数组v ,我希望能够构造一个VariantTuple<int, std::string> ,并使其与术语“1”和“a”匹配。 This introduces a host of other problems beyond the scope of my original question.这引入了超出我原来问题范围的许多其他问题。 But the question I'm interested in right now is whether it is even possible to construct a tuple based on an array in the first place.但我现在感兴趣的问题是,是否有可能首先基于数组构造一个元组。

Well I'm not sure if you're asking to dynamically deduce the number of vector elements and construct the tuple, which isn't possible, but here you go.好吧,我不确定您是否要求动态推导向量元素的数量并构造元组,这是不可能的,但您可以这样做。 I've used std::index_sequence to deduce the number of tuple elements depending of VariantTuple 's argument size.我使用std::index_sequence推断依据的元组的元素个数VariantTuple的说法大小。 This requires C++17 as it uses fold-expression.这需要 C++17,因为它使用折叠表达式。

#include <initializer_list>
#include <string>
#include <vector>
#include <tuple>
#include <utility>
#include <type_traits>
#include <ostream>
#include <iostream>

struct SimpleVariant
{
    SimpleVariant(int i) :                a(i), b("") {}
    SimpleVariant(const std::string& s) : a(0), b(s) {}

    operator int() const {
        return a;
    }

    operator std::string() const {
        return b;
    }

    int a;
    std::string b;
};

template<typename V, size_t... dim, typename... Args>
auto populate_tuple(const V& vec, std::index_sequence<dim...>, const std::tuple<Args...>& t) {
    return std::make_tuple(static_cast<std::remove_reference_t<decltype(std::get<dim>(t))>>(vec.at(dim))...);
}

template<size_t... dim, typename... Args>
std::ostream& dump_tuple(std::ostream& out, const std::tuple<Args...>& tpl, std::index_sequence<dim...>) {
    ((out << std::get<dim>(tpl) << ","), ...);
    return out;
}

template<typename... T>
struct VariantTuple
{
    VariantTuple(const std::vector<SimpleVariant>& v) : tpl(populate_tuple(v, std::make_index_sequence<sizeof...(T)>{}, tpl)) {}

    template<typename... V>
    friend std::ostream& operator <<(std::ostream& out, const VariantTuple<V...>& vt) {
        return dump_tuple(out, vt.tpl, std::make_index_sequence<sizeof...(V)>{});
    }
private:
    std::tuple<T...> tpl;
};

int main() {
    std::vector<SimpleVariant> v { 
        SimpleVariant(1),
        SimpleVariant(2),
        SimpleVariant("a") 
    };
    VariantTuple<int, int, std::string> t (v);
    std::cout << t << std::endl;

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM