获取 std::vector 的大小(通过扩展专门使用参数类型的可变参数模板函数来处理参数)

Getting size of std::vector (by extending variadic template functions working exclusively with parameter types to work with arguments)

本文关键字:参数 变参 类型 函数 处理 vector std 获取 扩展      更新时间:2023-10-16

我正在尝试扩展计算模板包类型大小的代码,以便能够获取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;
}

虽然干杯和呵呵。 - Alf 评论了我的问题,准确地描述了这段代码,我在看到评论之前自己写的。