获取 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 函数 Tsstd::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 评论了我的问题,准确描述了这段代码,我在看到评论之前自己写的。