让我们有一个结构记录{uint8_t x,y;}
,一个容器
容器
如何使用模板从容器中获取
Transposed
?
我尝试过变量模板,
#include <iostream>
#include <vector>
template <typename value_type=uint8_t> struct Record{
value_type x, y;
};
template<typename value_type, typename value_type2=uint8_t> class ContainerA: public std::vector<value_type>{
value_type2 b=1u;
};
template<typename value_type, uint8_t int_value=1u> class ContainerB: public std::vector<value_type>{};
template<typename value_type, template <typename ...> typename container_type> class Transposed{
container_type<value_type> x, y;
public:
Transposed(container_type<Record<value_type>> & recs){
x.reserve(recs.size());
y.reserve(recs.size());
x.resize(recs.size());
y.resize(recs.size());
size_t i=0;
for(auto &rec :recs){
x[i] = rec.x;
y[i] = rec.y;
++i;
}
}
};
int main(){
std::vector<Record<uint8_t>> recsV{
{1, 2},
{3, 4}
};
Transposed trV{recsV};
std::cout<<"vec"<<std::endl;
ContainerA<Record<uint8_t>> recsA{
{1, 2},
{3, 4}
};
Transposed trA{recsA};
std::cout<<"A"<<std::endl;
/*ContainerB<Record<uint8_t>> recsB{
{1, 2},
{3, 4}
};
Transposed trB{recsB};
std::cout<<"B"<<std::endl;*/
return 0;
}
但它们似乎无法同时匹配类型和值。不允许使用多个可变模板参数。这是C语言中的一个缺陷还是故意的设计选择?我们是否需要类似于
any\u template\u arg
关键字之类的东西,还是应该只指定两个不同类型的可变参数就可以允许这个用例?
您可以举一个工作示例:
template<typename value_type=uint8_t>
struct Record{
value_type x, y;
};
template<class T>
std::vector<T> rebind_container(std::vector<Record<T>> const&);
// Span transposes into vector.
template<class T>
std::vector<T> rebind_container(std::span<Record<T>> const&);
template<class T>
std::list<T> rebind_container(std::list<Record<T>> const&);
inline void reserve(...) {}
template<class... Args>
inline void reserve(std::vector<Args...>* v, size_t n) {
v->reserve(n);
}
template<class container_type>
struct Transposed {
using container_type2 = decltype(rebind_container(std::declval<container_type>()));
container_type2 x, y;
Transposed(container_type const& recs) {
auto const n = recs.size();
reserve(&x, n);
reserve(&y, n);
for(auto& rec : recs) {
x.push_back(rec.x);
y.push_back(rec.y);
}
}
};
int main(){
std::vector<Record<uint8_t>> recsV{
{1, 2},
{3, 4}
};
Transposed<decltype(recsV)> trV{recsV};
std::cout << trV.x.size() << std::endl;
std::list<Record<uint8_t>> recsV2{
{1, 2},
{3, 4}
};
Transposed<decltype(recsV2)> trV2{recsV2};
std::cout << trV2.x.size() << std::endl;
}
据我所知,没有一种方法可以将类型和值(以及模板)模板参数匹配在一起。我已经找了很久了。
所以我看不到一种简单优雅的方式来制作你想要的东西。
试着回答你的问题
如何使用模板从容器中获取Transposed
?
我所能想到的最好的方法是声明(不必定义它们,只在decltype()
中使用计数)几个简单的函数,如下所示
template <typename VT,
template <typename...> typename CT>
CT<VT> extract_func (CT<Record<VT>>);
template <typename VT,
template <typename, auto...> typename CT>
CT<VT> extract_func (CT<Record<VT>>);
第一个是当CT
容器接受不同类型列表(std::向量
和ContainerA
大小写)时删除记录
部分;第二个是用于容器CT接受(在类型参数之后)一个或多个值(
ContainerB
case)。
显然,这并没有涵盖所有可能的情况,但声明其他
extract_func()
函数来涵盖其他情况并不重要。
现在,您可以如下声明
transposed
template <typename T,
typename CT = decltype(extract_func(std::declval<T>()))>
class Transposed
请注意,现在,
Transposed
接受泛型类型T
,但仅当T
类型匹配(作为参数)extract_func()
声明时才启用SFINAE。
在
Transposed
主体中,可以使用CT
声明构造函数参数的x
和y
和T
。
下面是一个完整的编译示例
#include <iostream>
#include <vector>
template <typename value_type=std::uint8_t>
struct Record
{ value_type x, y; };
template <typename value_type, typename value_type2=std::uint8_t>
class ContainerA : public std::vector<value_type>
{ value_type2 b=1u; };
template <typename value_type, std::uint8_t int_value=1u>
class ContainerB : public std::vector<value_type>
{ };
template <typename VT,
template <typename...> typename CT>
CT<VT> extract_func (CT<Record<VT>>);
template <typename VT,
template <typename, auto...> typename CT>
CT<VT> extract_func (CT<Record<VT>>);
template <typename T,
typename CT = decltype(extract_func(std::declval<T>()))>
class Transposed
{
private:
CT x, y;
public:
Transposed (T & recs)
{
x.reserve(recs.size());
y.reserve(recs.size());
x.resize(recs.size());
y.resize(recs.size());
std::size_t i=0u;
for(auto &rec :recs){
x[i] = rec.x;
y[i] = rec.y;
++i;
}
}
};
int main ()
{
std::vector<Record<std::uint8_t>> recsV { {1, 2}, {3, 4} };
Transposed trV{recsV};
std::cout<<"vec"<<std::endl;
ContainerA<Record<std::uint8_t>> recsA { };
Transposed trA{recsA};
std::cout<<"A"<<std::endl;
ContainerB<Record<std::uint8_t>> recsB { };
Transposed trB{recsB};
std::cout<<"B"<<std::endl;
}
3.2.1 配置结构 当默认的工程结构不适用的时候,你可能需要配置它。根据 Gradle 文档说明,可以通过如下方式重新配置Java工程的 sourceSets: sourceSets { main { java { srcDir 'src/java' } resources { srcDir
当默认的项目结构不适用时,可以自定义配置。查看 Gradle 文档中 Java plugin 部分以了解如何在纯 Java 项目中进行配置。 Android plugin 使用了类似的语法,但因为 Android 有自己的 sourceSets,所以需要配置到 android 块中。下面的例子使用了旧的项目结构(Eclipse),并把 androidTest 的 sourceSet 映射到 tes
本部分讨论三个库:Boost.Any, Boost.Variant, 和 Boost.Tuple. 在某种意义上,它们都是容器,虽然它们与标准库的容器类毫无共同之处。它们都是非常有用的库,许多人和我一样,每天都在使用它们来解决编程上的问题。它们 所解决的问题是C++或C++标准库所未能覆盖的范畴,因此它们确实是我们的库工具箱的非常重要的扩展。想一下基础数据结构的有效性将影响我们编程及设计 的方法,
这是我关于Stackoverflow的第一个问题,所以如果你在我的第一个帖子中发现任何荒谬的东西,请耐心等待。我已经看过SO FAQ了,我知道它的各种政策。您知道,我是一个大量使用PHP、Perl、Python、ROR等语言的人,最近我“上下文切换”到Java EE。您知道,我研究过的几种语言都有一个构造,使我能够递归地转储聚合结构的内容,而不需要for/foreach/for.in循环 例如,
扁平数组的结构如上,每个目录下都可以添加数据 如何将这个数组转成树形的结构啊,转成如下的形式 目录层级的name就取对应的 xxxLevelStr
谁能给我解释一下这个吗?