简体   繁体   English

具有可变参数的嵌套C ++模板

[英]Nested C++ template with variadic

I was wondering if it was possible to have nested C++ template and still be able to access the template values ? 我想知道是否可以嵌套C ++模板并仍能访问模板值? To explain, here is what I currently have: 为了解释,这是我目前拥有的:

template <int first, int... tail>
struct ConstIntVector:ConstIntVector<tail...>
{};

template <int first>
struct ConstIntVector<first>
{}; 

template<int f1, int... t1>
int prod(const ConstIntVector<f1, t1...>, const int* a) {
    return f1 * (*a) + prod(ConstIntVector<t1...>(), a+1);
}

This way, I can access the f1 value in my prod function. 这样,我可以访问我的prod函数中的f1值。 But I would like to do it like this: 但我想这样做:

template<ConstIntVector<int f1, int... t1>>
int prod(const int* a) {
    return f1 * (*a) + prod<ConstIntVector<t1...>>(a+1);
}

It is possible ? 有可能的 ?

Partial template specializations aren't allowed for member functions. 成员函数不允许使用部分模板特化。 But you can use a helper struct: 但是你可以使用一个辅助结构:

namespace detail
{
    template <typename T>
    struct prodHelper;

    template <int f1, int... t1>
    struct prodHelper<ConstIntVector<f1, t1...> >
    {
        static int eval(const int* a) { 
            return f1 * (*a) + prodHelper<ConstIntVector<t1...>>::eval(a+1);
        }
    };
}

template <typename T>
int prod(const int* a) {
    return detail::prodHelper<T>::eval(a);
}

Another option would be to utilize ConstIntVector structs to carry useful information: 另一个选择是利用ConstIntVector结构来携带有用的信息:

template <int First, int... Tail>
struct ConstIntVector {
   constexpr static int value = First;
   using tail = ConstIntVector<Tail...>;
};

template <int First>
struct ConstIntVector<First> {
   constexpr static int value = First;
   using got_no_tail = void;
}; 

template <class CIV, typename CIV::tail* = nullptr>
int prod(const int* a) {
    return CIV::value * (*a) + prod<typename CIV::tail>(a+1);
}

template <class CIV, typename CIV::got_no_tail* = nullptr>
int prod(const int* a) {
    return CIV::value * (*a);
}

Just be aware, that recursion is neither necessary nor desirable to solve these kinds of TMP problems. 请注意,递归对于解决这些类型的TMP问题既不必要也不可取。 First, it is better to simply define your vector like this: 首先,最好简单地定义你的矢量:

template <int... Is>
struct ConstIntVector{};

That way you can have zero length vectors as well, which is convenient in handling edge cases (witness the fact that std::array can be length 0). 这样你也可以有零长度向量,这在处理边缘情况时很方便(见证了std::array长度为0的事实)。

Next, lets write our product function. 接下来,让我们编写产品功能。 We'll modify it in two ways: first we'll infer the integer by trivially passing our ConstIntVector by value, and second we'll use pack expansions to avoid recursion. 我们将通过两种方式对其进行修改:首先我们通过按值传递我们的ConstIntVector来推断整数,然后我们将使用包扩展来避免递归。

template<int... Is>
int prod(const int* a, ConstIntVector<Is...>) {
    int index = 0;
    int sum = 0;
    int [] temp = {(sum += (a[index++] * Is))...};
    return sum;
}

Usage: 用法:

std::vector<int> v{1,2,3};
using v2 = ConstIntVector<4,5,6>;
std::cerr << prod(v.data(), v2{});

Live example: http://coliru.stacked-crooked.com/a/968e2f9594c6b292 实例: http//coliru.stacked-crooked.com/a/968e2f9594c6b292

Link to example of highly optimized assembly: https://godbolt.org/g/oR6rKe . 链接到高度优化的装配示例: https//godbolt.org/g/oR6rKe

How about 怎么样

template<int I>
int prod(const int* a) {
    return I * (*a);
}

template<int I, int I2, int... Is>
int prod(const int* a) {
    return I * (*a) + prod<I2, Is...>(a + 1);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM