创建一个像std :: integral_constant这样的容器

时间:2017-01-18 16:36:01

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

我想创建一个"容器版本" 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);    
}

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

现在我想要一个辅助函数来创建这样一个类型而不指定(冗余)枚举类型。

这里的输出是:

2
0

任何提示?

2 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:3)

作为您对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<T>而不是T s;它有点吵闹,但变量模板使它不会痛苦:

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

(另外,演示becomes unnecessary in C++17static_container::value的单独定义。)