【问题标题】:Create a container like std::integral_constant创建一个像 std::integral_constant 这样的容器
【发布时间】:2017-06-03 03:25:57
【问题描述】:

我想创建一个std::integral_constant 的“容器版本”。那是用元素类型和非类型参数参数化的类型:

enum class A {
    a = 1 << 0, 
    b = 1 << 1, 
    c = 1 << 2
};

template<typename T, T... Values>
struct static_container final {};

template<typename T, T... Ts>
constexpr auto make_static_container(T...) { // wrong
    return static_container<T, Ts...>{};
}

template<typename F, F... FF>
void inline set(static_container<F, FF...>) {
    std::cout << sizeof... (FF) << std::endl;
}

int main() {
    constexpr static_container<A, A::a, A::b> sc1{}; //ok
    constexpr auto sc2 = make_static_container(A::a, A::c); // not-ok

    set(sc1);    
    set(sc2);    
}

上面你可以看到我可以用显式类型创建sc1

现在我喜欢有一个辅助函数来创建这样的类型,而无需指定(冗余)枚举类型。

这里的输出是:

2
0

有什么提示吗?

【问题讨论】:

  • 您遇到什么错误以及使用什么编译器?
  • 在 VS2015 上编译
  • 抱歉这里不清楚:没有编译错误,但是“容器”是空的。

标签: c++ c++11 c++14 variadic-templates constexpr


【解决方案1】:

作为您对 std::integral_constant 评论的后续行动,以下是您的评论:

template<typename T, T... Values>
constexpr auto make_static_container(std::integral_constant<T, Values>...) noexcept {
    return static_container<T, Values...>{};
}

调用站点必须更改,因为该函数现在直接使用std::integral_constant&lt;T&gt;s 而不是Ts;它有点吵,但变量模板使它不会痛苦:

template<A a>
using A_ = std::integral_constant<A, a>;

template<A a>
constexpr A_<a> a_{};

int main() {
    // explicit construction via alias template:
    constexpr auto sc1 = make_static_container(A_<A::a>{}, A_<A::b>{});
    // implicit construction via variable template:
    constexpr auto sc2 = make_static_container(a_<A::a>, a_<A::c>);

    set(sc1);
    set(sc2);
}

Online Demo

(顺便说一句,演示中static_container::value的单独定义becomes unnecessary in C++17。)

【讨论】:

  • 模板变量的有趣想法。
  • @wimalopaan :直到最近我对它们没有意见或使用它们,但最近使用Boost.Hana 给了我新的视角。 :-]
【解决方案2】:

您的问题是您没有将函数的参数传递给返回值创建的模板参数列表

template<typename T, T... Ts>
constexpr auto make_static_container(T... /* !!! unused values !!! */) { // wrong
    return static_container<T, Ts...>{};
}

所以唯一推导出的模板是T;没有推导出模板非类型值Ts;所以返回的类型是

return static_container<T>{};

那是零值。

您应该能够使用函数的参数并将它们作为模板而不是类型参数传递;像

template<typename T0, typename ... Ts>
constexpr auto make_static_container (T0 const t0, Ts const ... ts)
 { return static_container<T0, t0, ts...>{}; }

但这在 C++11/C++14 中是不可能的(据我所知),因为 t0/ts 值不是 constexpr

【讨论】:

  • 是的,这确实是不可能的,因为 constexpr 函数也必须在非 constexpr 上下文中可调用。
  • 我想知道是否可以使用 std::integral_constant 作为 make_static_container 的模板模板参数以及 make_static_container 的显式实例化而不是参数列表的解决方案......但我可以'做对了。
猜你喜欢
  • 1970-01-01
  • 2015-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-04
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多