创建 N 个零的 index_sequence
Creating an index_sequence of N zeros
我一直在尝试编写一个 zero_sequence
类型,它创建一个 index_sequence
指定数量的零或使用现有的
index_sequence
以生成一个具有相同数量值但全为零的新值。我很困惑为什么会这样:
template<typename> struct zero_sequence;
template<size_t...I>
struct zero_sequence<index_sequence<I...>> : index_sequence<(I*0u)...>{};
int main( int argc, char *argv[] ) {
using A = index_sequence<0,1,2,3,4>;
using B = make_index_sequence<5>;
using A0 = zero_sequence<A>;
using B0 = zero_sequence<B>;
A a; B b;
cout <<< std::is_same<A,B>::value << endl; // is false
A0 a0;
B0 b0; // < error implicit instantiation of undefined template
return 0;
}
我不明白为什么这两种情况不同(在 Mac Clang llvm 9.0.0 上)。
如果与解释此行为相关,我将在 C++11 I think I got it from here:
中使用 index_sequence
和 make_index_sequence
的以下实现
template<typename Integer, Integer... I>
struct integer_sequence {
using type = integer_sequence;
using value_type = Integer;
static constexpr size_t size() noexcept { return sizeof...(I); }
};
template<size_t... Ints> using index_sequence = integer_sequence<size_t, Ints...>;
template <typename,typename> struct _merge_and_renumber;
template <size_t... I1, size_t... I2>
struct _merge_and_renumber<index_sequence<I1...>,index_sequence<I2...>>
: index_sequence<I1..., (sizeof...(I1)+I2)...> {};
template <size_t N>
struct make_index_sequence
: _merge_and_renumber<typename make_index_sequence<N/2>::type,
typename make_index_sequence<N - N/2>::type> {};
template<> struct make_index_sequence<0> : index_sequence<> {};
template<> struct make_index_sequence<1> : index_sequence<0> {};
我建议 zero_sequence
完全不同:不是 struct
而是基于 decltype()
、std::declval()
和唯一声明的助手的 using
函数(遵循 std::declval()
示例。
我的意思是...如果您定义以下辅助函数
template <std::size_t ... Is>
constexpr auto zeHelper (index_sequence<Is...> const &)
-> decltype( index_sequence<(Is,0u)...>{} );
zero_sequence
可以定义为
template <typename T>
using zero_sequence = decltype(zeHelper(std::declval<T>()));
你可以声明 a0
和 b0
A0 a0;
B0 b0; // now works
编译也没有问题
static_assert( std::is_same<A0, B0>::value, "!" );
I'm perplexed as to why this is happening [...] I don't understand why the two cases are different
你的 zero_sequence
模板结构特化的问题
template<size_t...I>
struct zero_sequence<index_sequence<I...>> : index_sequence<(I*0u)...>{};
是不是还有通用版(未实现,但是有)
template<typename> struct zero_sequence;
因此,当您使用 index_sequence
作为 zero_sequence
的模板参数时,实现的特化匹配并被选中。
但是当您使用 make_index_sequence
时,它继承自 index_sequence
并且可以转换为 index_sequence
但不完全是 index_sequence
,专业化不会'匹配并选择 zero_sequence
的通用(未实现)版本。
通过一个函数,我建议的 zeHelper()
或类似的东西,避免了这个问题,因为 make_index_sequence
可以转换为 index_sequence
.
我一直在尝试编写一个 zero_sequence
类型,它创建一个 index_sequence
指定数量的零或使用现有的
index_sequence
以生成一个具有相同数量值但全为零的新值。我很困惑为什么会这样:
template<typename> struct zero_sequence;
template<size_t...I>
struct zero_sequence<index_sequence<I...>> : index_sequence<(I*0u)...>{};
int main( int argc, char *argv[] ) {
using A = index_sequence<0,1,2,3,4>;
using B = make_index_sequence<5>;
using A0 = zero_sequence<A>;
using B0 = zero_sequence<B>;
A a; B b;
cout <<< std::is_same<A,B>::value << endl; // is false
A0 a0;
B0 b0; // < error implicit instantiation of undefined template
return 0;
}
我不明白为什么这两种情况不同(在 Mac Clang llvm 9.0.0 上)。
如果与解释此行为相关,我将在 C++11 I think I got it from here:
中使用index_sequence
和 make_index_sequence
的以下实现
template<typename Integer, Integer... I>
struct integer_sequence {
using type = integer_sequence;
using value_type = Integer;
static constexpr size_t size() noexcept { return sizeof...(I); }
};
template<size_t... Ints> using index_sequence = integer_sequence<size_t, Ints...>;
template <typename,typename> struct _merge_and_renumber;
template <size_t... I1, size_t... I2>
struct _merge_and_renumber<index_sequence<I1...>,index_sequence<I2...>>
: index_sequence<I1..., (sizeof...(I1)+I2)...> {};
template <size_t N>
struct make_index_sequence
: _merge_and_renumber<typename make_index_sequence<N/2>::type,
typename make_index_sequence<N - N/2>::type> {};
template<> struct make_index_sequence<0> : index_sequence<> {};
template<> struct make_index_sequence<1> : index_sequence<0> {};
我建议 zero_sequence
完全不同:不是 struct
而是基于 decltype()
、std::declval()
和唯一声明的助手的 using
函数(遵循 std::declval()
示例。
我的意思是...如果您定义以下辅助函数
template <std::size_t ... Is>
constexpr auto zeHelper (index_sequence<Is...> const &)
-> decltype( index_sequence<(Is,0u)...>{} );
zero_sequence
可以定义为
template <typename T>
using zero_sequence = decltype(zeHelper(std::declval<T>()));
你可以声明 a0
和 b0
A0 a0;
B0 b0; // now works
编译也没有问题
static_assert( std::is_same<A0, B0>::value, "!" );
I'm perplexed as to why this is happening [...] I don't understand why the two cases are different
你的 zero_sequence
模板结构特化的问题
template<size_t...I>
struct zero_sequence<index_sequence<I...>> : index_sequence<(I*0u)...>{};
是不是还有通用版(未实现,但是有)
template<typename> struct zero_sequence;
因此,当您使用 index_sequence
作为 zero_sequence
的模板参数时,实现的特化匹配并被选中。
但是当您使用 make_index_sequence
时,它继承自 index_sequence
并且可以转换为 index_sequence
但不完全是 index_sequence
,专业化不会'匹配并选择 zero_sequence
的通用(未实现)版本。
通过一个函数,我建议的 zeHelper()
或类似的东西,避免了这个问题,因为 make_index_sequence
可以转换为 index_sequence
.