获取 std::vector 的大小(通过扩展可变参数模板函数来处理参数类型)
Getting size of std::vector (by extending variadic template functions working exclusively with parameter types to work with arguments)
我正在尝试扩展计算模板包类型大小的代码,以便能够获得 std::vector<T>
实例的大小(我对向量大小的概念是 std::vector<T>::size() * sizeof(T)
)。原代码如下:
template <class T>
constexpr size_t getSize_single()
{
return sizeof(T);
}
// specialized case
template<>
constexpr size_t getSize_single<double>()
{
return SIZEOF_DOUBLE;
}
template <class... Ts>
size_t getSize()
{
// handles the case of Ts being empty
std::initializer_list<size_t> l{getSize_single<Ts>()...};
size_t sum = 0;
for(auto s : l) sum += s;
return sum;
}
我喜欢
template <class ...T>
void foo(T... arg)
{
std::cout << getSize<T...>() << std::endl;
}
// main
foo(11.123456789, 1.12345, 2.12345, 3.12345);
我对扩展它以使用 std::vector<T>
的看法如下:
由于我们需要获取 std::vector<T>
实例的大小,因此我们需要访问它,我们通过将其传递给 getSize()
来实现,这会将其更改为
template <class ...T>
void foo(T... arg)
{
std::cout << getSize(arg...) << std::endl;
}
// main
foo(11.123456789, std::vector<double>{1.12345, 2.12345, 3.12345});
然后
template <class T>
constexpr size_t getSize_single()
{
return sizeof(T);
}
template<>
constexpr size_t getSize_single<double>()
{
return SIZEOF_DOUBLE;
}
// arg_tag_val<T> hack for std::vector to work
template <typename T> struct arg_tag_val {const T &t;};
template <class T>
constexpr size_t getSize_single(arg_tag_val<T>)
{
return getSize_single<T>();
}
template<>
constexpr size_t getSize_single<double>(arg_tag_val<double>)
{
return getSize_single<double>();
}
template<>
constexpr size_t getSize_single<float>(arg_tag_val<float>)
{
return getSize_single<float>();
}
template <class T>
size_t getSize_single(arg_tag_val<std::vector<T>> v)
{
return v.t.size() * getSize_single<T>();
}
template <class... Ts>
size_t getSize(const Ts&... arg)
{
// handles the case of Ts being empty
std::initializer_list<size_t> l{getSize_single<Ts>(arg_tag_val<Ts>{arg})...};
size_t sum = 0;
for(auto s : l) sum += s;
return sum;
}
但它失败了,因为在底部 getSize
函数 Ts
是 std::vector<double>
并且 getSize_single
被调用为 getSize_single<std::vector<double>>(arg_tag_val<std::vector<double>>{vec})
,它调用 constexpr size_t getSize_single(arg_tag_val<T>)
而不是 size_t getSize_single(arg_tag_val<std::vector<T>> v)
.
我被困在这里,不知道如何让它工作,因此寻求帮助。
我仅限于 C++11。
看起来我的第一次尝试完全是过度设计的。如果我们摆脱 arg_tag_val
参数包装器并使用实际参数,那么一切都会正常。
template <class T>
size_t getSize_single(T&)
{
return sizeof(T);
}
// specialized case
template<>
size_t getSize_single<double>(double&)
{
return SIZEOF_DOUBLE;
}
template <class T>
size_t getSize_single(std::vector<T>& v)
{
size_t size = 0;
if (v.size() > 0) {
size += v.size() * getSize_single(v[0]);
}
return size;
}
template <class... Ts>
size_t getSize(Ts&... arg)
{
// handles the case of Ts being empty
std::initializer_list<size_t> l{getSize_single(arg)...};
size_t sum = 0;
for(auto s : l) sum += s;
return sum;
}
虽然干杯和hth。 - Alf 评论了我的问题,准确描述了这段代码,我在看到评论之前自己写的。
我正在尝试扩展计算模板包类型大小的代码,以便能够获得 std::vector<T>
实例的大小(我对向量大小的概念是 std::vector<T>::size() * sizeof(T)
)。原代码如下:
template <class T>
constexpr size_t getSize_single()
{
return sizeof(T);
}
// specialized case
template<>
constexpr size_t getSize_single<double>()
{
return SIZEOF_DOUBLE;
}
template <class... Ts>
size_t getSize()
{
// handles the case of Ts being empty
std::initializer_list<size_t> l{getSize_single<Ts>()...};
size_t sum = 0;
for(auto s : l) sum += s;
return sum;
}
我喜欢
template <class ...T>
void foo(T... arg)
{
std::cout << getSize<T...>() << std::endl;
}
// main
foo(11.123456789, 1.12345, 2.12345, 3.12345);
我对扩展它以使用 std::vector<T>
的看法如下:
由于我们需要获取 std::vector<T>
实例的大小,因此我们需要访问它,我们通过将其传递给 getSize()
来实现,这会将其更改为
template <class ...T>
void foo(T... arg)
{
std::cout << getSize(arg...) << std::endl;
}
// main
foo(11.123456789, std::vector<double>{1.12345, 2.12345, 3.12345});
然后
template <class T>
constexpr size_t getSize_single()
{
return sizeof(T);
}
template<>
constexpr size_t getSize_single<double>()
{
return SIZEOF_DOUBLE;
}
// arg_tag_val<T> hack for std::vector to work
template <typename T> struct arg_tag_val {const T &t;};
template <class T>
constexpr size_t getSize_single(arg_tag_val<T>)
{
return getSize_single<T>();
}
template<>
constexpr size_t getSize_single<double>(arg_tag_val<double>)
{
return getSize_single<double>();
}
template<>
constexpr size_t getSize_single<float>(arg_tag_val<float>)
{
return getSize_single<float>();
}
template <class T>
size_t getSize_single(arg_tag_val<std::vector<T>> v)
{
return v.t.size() * getSize_single<T>();
}
template <class... Ts>
size_t getSize(const Ts&... arg)
{
// handles the case of Ts being empty
std::initializer_list<size_t> l{getSize_single<Ts>(arg_tag_val<Ts>{arg})...};
size_t sum = 0;
for(auto s : l) sum += s;
return sum;
}
但它失败了,因为在底部 getSize
函数 Ts
是 std::vector<double>
并且 getSize_single
被调用为 getSize_single<std::vector<double>>(arg_tag_val<std::vector<double>>{vec})
,它调用 constexpr size_t getSize_single(arg_tag_val<T>)
而不是 size_t getSize_single(arg_tag_val<std::vector<T>> v)
.
我被困在这里,不知道如何让它工作,因此寻求帮助。
我仅限于 C++11。
看起来我的第一次尝试完全是过度设计的。如果我们摆脱 arg_tag_val
参数包装器并使用实际参数,那么一切都会正常。
template <class T>
size_t getSize_single(T&)
{
return sizeof(T);
}
// specialized case
template<>
size_t getSize_single<double>(double&)
{
return SIZEOF_DOUBLE;
}
template <class T>
size_t getSize_single(std::vector<T>& v)
{
size_t size = 0;
if (v.size() > 0) {
size += v.size() * getSize_single(v[0]);
}
return size;
}
template <class... Ts>
size_t getSize(Ts&... arg)
{
// handles the case of Ts being empty
std::initializer_list<size_t> l{getSize_single(arg)...};
size_t sum = 0;
for(auto s : l) sum += s;
return sum;
}
虽然干杯和hth。 - Alf 评论了我的问题,准确描述了这段代码,我在看到评论之前自己写的。