具有默认值的可变参数模板参数

问题描述 投票:2回答:2

我有一个模板化结构,它有一个方法(和其他参数一起)接受那些模板化参数。

template<class... Types>
struct Observer
{
    void subscribe(const std::string& id, Types... args)
    {
        // store id somehow
        data = std::make_tuple(args...);
    }

    std::tuple<Types...> data;
};

我想让所有模板化的参数都是可选的。所以它看起来像这样:

Observer<float, int> observer;
observer.subscribe("id1", 3.14, 4);
observer.subscribe("id2", 0.707); // this doesn't work!
observer.subscribe("id3");        // this doesn't work!

据我所知,有没有直接的方式?但也许有人知道一种解决方法或技巧。

理想情况下,我想提供自己的默认值。也许是这样的:

enum class SomeEnum { Val1, Val2 };    

Observer<float, SomeEnum, 0.f, SomeEnum::Val1> observer;
observer.subscribe("id1", 3.14);

这是LIVE EXAMPLE

c++ parameters c++14 variadic-templates
2个回答
2
投票

在C ++ 17中,您可以简单地执行以下操作:

template<class... Types>
struct Observer
{
    static constexpr std::tuple<Types...> defaults{42, 24, 99};

    template<class... Args>
    void subscribe(Args... args)
    {
        if constexpr (sizeof...(Types) > sizeof...(Args)) {
            subscribe(args..., std::get<sizeof...(Args)>(defaults));
        } else {
            // whatever you need with `args...`
        }
    }
};

在这里,我只是从Observer::defaults中挑选它们,但随意计算它们,无论你想要什么。

对于C ++ 14及更低版本,您需要模拟if constexpr。参见例如Constexpr if alternative替代品。


1
投票

Boost.Mp11获胜:

template <typename... Ts>
void subscribe(const std::string& id, Ts const&... args)
{
    static_assert(sizeof...(Ts) <= sizeof...(Types));
    using Rest = mp_drop_c<std::tuple<Types...>, sizeof...(Ts)>;
    data = std::tuple_cat(std::make_tuple(args...), Rest());
}

假设尾随参数的值初始化很好。如果不是,你将不得不弄清楚如何处理Us


如果您实际使可选更明确,则工作得更好:

template<class... Types>
struct Observer
{
    using Data = std::tuple<std::optional<Types>...>;

    template <typename... Ts>
    void subscribe(const std::string& id, Ts const&... args)
    {
        static_assert(sizeof...(Ts) <= sizeof...(Types));
        using Rest = mp_drop_c<Data, sizeof...(Ts)>;
        data = std::tuple_cat(std::make_tuple(args...), Rest());
    }

    Data data;
};
© www.soinside.com 2019 - 2024. All rights reserved.