std::initializer_list备选方案
std::initializer_list alternative
我正在尝试初始化我的自定义矢量对象,但没有使用std::initializer_list
。我正在做这样的事情:
template <typename T, std::size_t N>
struct vector
{
template<std::size_t I = 0, typename ...Tp>
typename std::enable_if<I == sizeof...(Tp), void>::type
unpack_tuple(std::tuple<Tp...> const& t)
{
}
template<std::size_t I = 0, typename ...Tp>
typename std::enable_if<I != sizeof...(Tp), void>::type
unpack_tuple(std::tuple<Tp...> const& t)
{
store[I] = std::get<I>(t);
unpack_tuple<I + 1, Tp...>(t);
}
template<typename ...U>
vector(U&&... args,
typename std::enable_if<std::is_scalar<U...>::value, void>::type* = 0)
{
unpack_tuple(std::forward_as_tuple(std::forward<U>(args)...));
}
T store[N];
};
但是编译器不会对构造函数进行grok,除非我删除std::enable_if
参数,我需要它(因为我不想要非标量参数)。是否存在解决方案?
std::is_scalar<U...>::value
问题在于is_scalar
只接受一个类型参数。您需要编写一个组合多个布尔值的包装器。我还想知道,如果你只想要标量类型,为什么要使用完美转发——只需按值传递它们。通过这种方式,您也不需要担心在传递左值时U
会被推导为引用。
#include <type_traits>
template<bool B>
using bool_ = std::integral_constant<bool, B>;
template<class Head, class... Tail>
struct all_of
: bool_<Head::value && all_of<Tail...>::value>{};
template<class Head>
struct all_of<Head> : bool_<Head::value>{};
template<class C, class T = void>
using EnableIf = typename std::enable_if<C::value, T>::type;
// constructor
template<typename... U>
vector(U... args, EnableIf<all_of<std::is_scalar<U>...>>::type* = 0)
{
unpack_tuple(std::tie(args...)); // tie makes a tuple of references
}
上面的代码应该可以工作。然而,作为一个建议,如果你不想要什么,static_assert
你没有得到,不要因此滥用SFINAE。:)SFINAE只能在重载上下文中使用。
// constructor
template<typename... U>
vector(U... args)
{
static_assert(all_of<std::is_scalar<U>...>::value, "vector only accepts scalar types");
unpack_tuple(std::tie(args...)); // tie makes a tuple of references
}
您的实际问题到此为止,但我建议使用索引技巧来解包元组(或一般的可变参数,甚至数组)的更好方法:
template<unsigned...> struct indices{};
template<unsigned N, unsigned... Is> struct indices_gen : indices_gen<N-1, N-1, Is...>{};
template<unsigned... Is> struct indices_gen<0, Is...> : indices<Is...>{};
template<unsigned... Is, class... U>
void unpack_args(indices<Is...>, U... args){
[](...){}((store[Is] = args, 0)...);
}
template<class... U>
vector(U... args){
static_assert(all_of<std::is_scalar<U>...>::value, "vector only accepts scalar types");
unpack_args(indices_gen<sizeof...(U)>(), args...);
}
此代码所做的是"滥用"可变的拆包机制。首先,我们生成一组索引[0 .. sizeof...(U)-1]
,然后与args
同步扩展此列表。我们把这个扩展放在一个可变(非模板)函数参数列表中,因为包扩展只能发生在特定的地方,这就是其中之一。另一种可能是作为本地阵列:
template<unsigned... Is, class... U>
void unpack_args(indices<Is...>, U... args){
int a[] = {(store[Is] = args, 0)...};
(void)a; // suppress unused variable warnings
}
相关文章:
- 运行同一解决方案的另一个项目的项目
- Project Euler问题4的错误解决方案
- 计算每个节点的树高,帮助我解释这个代码解决方案
- C++:Application.cpp中抛出了未解析的外部符号(解决方案在问题的末尾,供未来的读者参考)
- visual c++,如何获取解决方案目录中的代码
- 有没有办法在远程设备上打开和编辑visual Studio 2017解决方案
- C++Matching Brackets 2解决方案不起作用
- 在 ubuntu3 上C++ goto 定义有什么解决方案吗16.04?
- C++11 中不同类型的对象的 std::array 的替代方案
- 在 leetcode 上提交解决方案时出现堆栈缓冲区溢出错误
- 别名模板的专业化 C++11 中没有开销的最佳替代方案
- 我的固定时间步长与增量时间和插值的解决方案是错误的吗?
- 无法在问题解决方案中执行输出逻辑
- 最大的回文产品 - 程序未运行,编写解决方案但无法理解问题
- 从预序遍历构造 bst 的 c++ 和 python 解决方案之间的区别
- 在一个解决方案中针对第三方静态库 (Creo) 的不同版本(版本)进行构建
- 如何巧妙地编写两个函数——一个用于检查是否存在解决方案,另一个用于获取所有解决方案
- 使用 Git 处理 C++ Visual Studio 2019 解决方案的外部依赖项源代码管理的最佳方法是什么?
- N-queen问题:无法弄清楚为什么我的解决方案不起作用
- 从排序数组中删除重复项,具有不同代码方式的相同解决方案具有不同的输出