Dav*_*man 5 c++ templates language-lawyer template-argument-deduction
考虑下面的代码片段,我们试图在该代码片段中推断出函数的template参数foobar():
struct Bar { static constexpr auto size = 5; };
template <class T, class=std::make_index_sequence<T::size>>
struct FooList;
template <class T, std::size_t... Idxs>
struct FooList<T, std::integer_sequence<std::size_t, Idxs...>> { };
struct Wrapper {
template <class T>
using list_type = FooList<T>;
};
template <class T>
void foobar(typename Wrapper::template list_type<T>) { }
void test() {
foobar(FooList<Bar>{});
}
Run Code Online (Sandbox Code Playgroud)
主要的编译器前端在是否应进行编译方面存在分歧(请参阅this godbolt)。如果我们显式地指定template参数,例如:
void test_explicit() {
foobar<Bar>(FooList<Bar>{});
}
Run Code Online (Sandbox Code Playgroud)
所有主要的前端都能成功地编译代码(godbolt)。有趣的是,如果我们简化推论:
struct Bar { };
struct Wrapper {
template <class T>
using my_type = T;
};
template <class T>
void foobar(typename Wrapper::template my_type<T>) { }
void test() {
foobar(Bar{});
}
Run Code Online (Sandbox Code Playgroud)
前端的另一个子集会编译而无法编译(MSVC是同时编译两者的唯一子集,请参阅此Godbolt)。
哪种实现符合此处的要求,哪些是错误的(为什么)?谁能找到C ++标准中指定其工作方式的部分?
正如评论中所讨论的,这是__make_integer_seq. 我想提供一个解决方法:
#include <utility>
namespace workaround {
#ifdef __clang__
template<class T, T N>
struct make_index_sequence_helper {
using type = __make_integer_seq<std::integer_sequence, T, N>;
};
template<class T, T N>
using make_integer_sequence = typename make_index_sequence_helper<T, N>::type;
template<std::size_t N>
using make_index_sequence = make_integer_sequence<std::size_t, N>;
#else
using std::make_integer_sequence;
using std::make_index_sequence;
#endif
}
Run Code Online (Sandbox Code Playgroud)
然后再次在作品中使用它FooList:
template <class T, class=workaround::make_index_sequence<T::size>>
struct FooList;
template <class T, std::size_t... Idxs>
struct FooList<T, std::integer_sequence<std::size_t, Idxs...>> { };
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
90 次 |
| 最近记录: |