我想知道是否可以使用向量作为向量的初始值设定项列表。所以,如果我有
struct somedata{
string str1;
string str2;
}
struct moredata{
string str1;
string str2;
string str3;
}
template<class Dataholder>
Dataholder queryUser(args){
auto vec = get_vector_from_user(args)
Dataholder dat{vec}; // The elements of vec become the structured variables in dat.
return dat;
}
因此,当调用 get_vector_from_user()
时,用户可能会输入 2 或 3 个字符串。但是,我知道程序员将始终使用模板 queryUser
,并且 vec
中的元素数量与 Dataholder
模板中的字符串数量相同。是否可以使用向量的成员初始化结构?谢谢!
答案 0 :(得分:4)
对于有问题的类,编写一个接受 std::vector
的构造函数,或者直接在函数模板中包含逻辑:
struct somedata{
string str1;
string str2;
somedata(const std::vector& vec) : str1(vec[0]), str2(vec[1]){
}
}
struct moredata{
string str1;
string str2;
string str3;
moredata(const std::vector& vec) : str1(vec[0]), str2(vec[1]), str3(vec[2]){
}
}
template<class Dataholder>
Dataholder queryUser(args){
auto vec = get_vector_from_user(args)
Dataholder dat{vec}; // The elements of vec become the structured variables in dat.
return dat;
}
只需确保添加一个检查以断言向量中的元素数量正确。
答案 1 :(得分:3)
是的,这是可能的。枚举结构成员需要复杂的模板,并且可能需要代码生成,因为您可能需要为每个特定数量的结构成员提供样板代码。幸运的是,有一个图书馆可以做到这一点。看Boost.PFR,又名magic_get
。
它的界面模仿std::tuple
的界面,所以很容易使用。
两个主要限制是:
您还需要一个编译时 for
循环:
template <typename Integer, Integer ...I, typename F>
constexpr void constexpr_for_each(std::integer_sequence<Integer, I...>, F &&func)
{
(func(std::integral_constant<Integer, I>{}) , ...);
}
template <auto N, typename F>
constexpr void constexpr_for(F &&func)
{
if constexpr (N > 0)
constexpr_for_each(std::make_integer_sequence<decltype(N), N>{}, std::forward<F>(func));
}
现在你可以这样做:
struct A
{
std::string x;
std::string y;
std::string z;
};
int main()
{
std::vector<std::string> vec = {"a", "b", "c"};
if (vec.size() != boost::pfr::tuple_size_v<A>)
throw std::runtime_error("Wrong vector size.");
A a;
constexpr_for<boost::pfr::tuple_size_v<A>>([&](auto index)
{
constexpr auto i = index.value;
static_assert(std::is_same_v<std::string, boost::pfr::tuple_element_t<i, A>>);
boost::pfr::get<i>(a) = vec[i];
});
std::cout << a.x << ' ' << a.y << ' ' << a.z << '\n'; // a b c
}