我想创建一个"容器版本" 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
任何提示?
答案 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++17中static_container::value
的单独定义。)