【问题标题】:Print template parameters打印模板参数
【发布时间】:2021-05-23 12:00:13
【问题描述】:

我正在尝试创建一个任意数量的 int 参数的模板向量并创建一个函数来打印这些参数:

namespace ex {

    template <int I, class... Ts>
    constexpr decltype(auto) get(Ts&& ... ts) {
        return std::get<I>(std::forward_as_tuple(ts...));
    }

    template<int... N>
    struct vec
    {
        static const int size = sizeof...(N);
        void print() {
            print(size-1);
        }

        void print(const int n) {
            if (n >= 0) {
                print(n - 1);
                std::cout << ex::get<n>(N...) << std::endl;
            }
        }
    };
}

int main()
{
    ex::vec<1, 2, 3> v;
    v.print();
}

我收到以下错误:

error C2672: 'ex::get': no matching overloaded function found
error C2975: 'I': invalid template argument for 'ex::get', expected compile-time constant expression

谁能解释我错过了什么以及如何实现我期望的行为?
提前致谢。

【问题讨论】:

    标签: c++ templates metaprogramming


    【解决方案1】:

    如果您可以访问 C++17,则可以从 fold expressions 中受益:

    template<int... N>
    struct vec {
        void print() {
            ((std::cout << N << std::endl), ...);
        }
    };
    

    在 C++17 之前,您可以使用虚拟数组初始化技巧:

    template<int... N>
    struct vec {
        void print() {
            int dummy[]{0, ((std::cout << N << std::endl), 0)...};
            (void)dummy;
        }
    };
    

    第一个零用于处理空的N... 包。第二个零是comma operator expression 的一部分。花括号列表中参数的评估顺序由它们在该列表中的顺序固定[dcl.init.list/4]


    但是如果我想对单个参数进行操作,例如,我想添加 operator+,它会添加 2 个向量。例如添加vec&lt;1,2,3&gt; v1vec&lt;4,5&gt; v2 将导致vec&lt;5,7,3&gt; v3?

    如果包可以有不同的大小,则需要一些技巧。例如:

    template<std::size_t... S, int... N, int... M>
    auto add_impl(vec<N...>, vec<M...>, std::index_sequence<S...>)
    {
        constexpr int is1[sizeof...(S)]{N...};
        constexpr int is2[sizeof...(S)]{M...};
        return vec<(is1[S] + is2[S])...>{};
    }
    
    template<int... N, int... M>
    auto operator+(vec<N...> v1, vec<M...> v2) {
        constexpr auto size = std::max(sizeof...(N), sizeof...(M));
        return add_impl(v1, v2, std::make_index_sequence<size>{});
    }
    

    【讨论】:

    • 感谢这封印的交易。但是,如果我想对单个参数进行操作,例如,我想添加 operator + 至此添加 2 个向量,该怎么办。例如添加 vec v1 和 vec v2 将产生 vec v3?
    • @EduardRostomyan,如果包的大小相同,这很容易:godbolt.org/z/or7scM。如果它们的大小不同,则需要一些技巧。
    • @EduardRostomyan,一种可能的技巧:godbolt.org/z/evWYEa
    猜你喜欢
    • 1970-01-01
    • 2013-06-04
    • 2021-05-19
    • 1970-01-01
    • 1970-01-01
    • 2022-01-14
    • 2018-08-13
    • 1970-01-01
    • 2012-09-02
    相关资源
    最近更新 更多