我想创建一个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
有什么提示吗?
作为您对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>
s而不是直接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);
}
在线演示
(顺便说一句,在 C++17 中,演示中对 static_container::value
的单独定义变得不必要。
您的问题是您没有将函数的参数传递给用于创建返回值的模板参数列表
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
值