为什么Clang无法使用默认的Integer_Sequence实例化嵌套的变异模板
Why clang is not able to instantiate nested variadic template with defaulted integer_sequence?
考虑一个示例:
#include <utility>
template <class... Ts>
struct pack {
static constexpr std::size_t size = sizeof...(Ts);
};
template <class P, class = std::make_index_sequence<P::size>>
struct ipack;
template <class... Ts, std::size_t... Is>
struct ipack<pack<Ts...>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};
template <class IP, class = std::make_index_sequence<IP::size>>
struct vpack;
template <class... Ts, std::size_t... Is>
struct vpack<ipack<pack<Ts...>>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};
int main() {
vpack<ipack<pack<int, int, int>>> vp;
static_cast<void>(vp);
}
clang报告以下问题:
prog.cc:29:39: error: implicit instantiation of undefined template 'vpack<ipack<pack<int, int, int>, std::__1::integer_sequence<unsigned long, 0, 1, 2> >, std::__1::integer_sequence<unsigned long, 0, 1, 2>
vpack<ipack<pack<int, int, int>>> vp;
^
GCC在这里没有分享叮当声。哪个编译器是对的?上面的代码是否以某种方式不正确?
我无法使用Godbolt重现您的错误。clang和GCC可以很好地编译。
但是,与编译器一起玩,我发现MSVC不喜欢您的代码,因为ipack
中的默认参数。但是,如果您直接提供参数,则可以工作:
template <class...Ts, std::size_t... Is>
struct vpack<ipack<pack<Ts...>,std::index_sequence<Is...>>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};
此更改也可以解决您的叮当声误差。(我不知道如何在Wandbox中获得链接...
编辑:
MSVC指出了另一个错误,我在上面省略了这一点。vpack
必须是可构造的。但是,由于您只是声明了它(struct vpack;
(,因此没有可用的默认构造函数。您可以通过以下方式定义:struct vpack {};
来解决此问题。这也解决了叮当问题。(即使没有上述。(
编辑2:
考虑为什么需要使用struct vpack {};
,我在代码中发现了另一个缺陷。它可以简化为:
#include <utility>
template <class... Ts>
struct pack {
static constexpr std::size_t size = sizeof...(Ts);
};
template <class P, class = std::make_index_sequence<P::size>>
struct ipack {};
template <class... Ts, std::size_t... Is>
struct ipack<pack<Ts...>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};
template <class IP, class = std::make_index_sequence<IP::size>>
struct vpack {};
int main() {
vpack<ipack<pack<int, int, int>>> vp;
static_cast<void>(vp);
}
原因是,vpack
的模板专业化没有实例化,是因为您使用了主模板的默认参数。(vpack<ipack<pack<int, int, int>>>
仅提供一个参数,而不是专业化所需的两个参数。(
您甚至可以删除ipack
的模板专业化,如果不是因为您在vpack
主中隐式使用它。(IP::size
是指ipack
的专业化。(
(我写了一个版本:https://godbolt.org/g/6gbsvd(
因此,MSVC和Wandboxes Clang拒绝编译您的代码是正确的。我不确定为什么它在GCC和Godbolts Clang下起作用。它可能必须通过处理默认参数的方式来做些事情...
有趣的是,您可以通过在vpack
中定义size
来看到差异:
#include <utility>
template <class... Ts>
struct pack {
static constexpr std::size_t size = sizeof...(Ts);
};
template <class P, class = std::make_index_sequence<P::size>>
struct ipack;
template <class... Ts, std::size_t... Is>
struct ipack<pack<Ts...>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};
template <class IP, class = std::make_index_sequence<IP::size>>
struct vpack { static constexpr std::size_t size = 0; };
template <class... Ts, std::size_t... Is>
struct vpack<ipack<pack<Ts...>,std::make_index_sequence<sizeof...(Ts)>>, std::index_sequence<Is...>> {
static constexpr std::size_t size = sizeof...(Ts);
};
int main() {
vpack<ipack<pack<int, int, int>>> vp;
return decltype(vp)::size;
}
GCC和Clang返回3
,但MSVC返回0
。
- 从C++实例化QML
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- 如何创建一个空的全局类并在启动时实例化它
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 约束和显式模板实例化
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 对象实例化调用构造函数的次数太多
- 如何使用非默认构造函数实例化模板化类
- 静态数据成员模板专用化的实例化点在哪里
- 错误的cv::face FacemarkLBF实例化
- C++的解析器在可以区分比较和模板实例化之前会做什么?
- 为什么 gcc 和 clang 为函数模板的实例化生成不同的符号名称?
- 检查某些类型是否是模板类 std::optional 的实例化
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- 无法使用 SWIG 在 Python 中实例化C++类(获取属性错误)
- 模板化类构造函数的模板实例化
- 在 c++ 中的模板实例化中使用带有构造函数的类作为类型参数
- 受约束的成员函数和显式模板实例化
- 对显式实例化的模板函数的未定义引用
- [temp.variadic]中关于包扩展实例化的措辞