C++ 有没有办法在编译时检查std::initializer\u列表中的参数数?
我试图创建一个函数,该函数将接受给定类型的多个参数,但参数的类型和数量都应通过模板指定 我发现在这种情况下,使用C++11的初始值设定项_list可能是一种很好的技术,但是否可以在编译时检查其大小?有没有其他技术可以解决这个问题C++ 有没有办法在编译时检查std::initializer\u列表中的参数数?,c++,templates,c++11,initializer-list,compile-time,C++,Templates,C++11,Initializer List,Compile Time,我试图创建一个函数,该函数将接受给定类型的多个参数,但参数的类型和数量都应通过模板指定 我发现在这种情况下,使用C++11的初始值设定项_list可能是一种很好的技术,但是否可以在编译时检查其大小?有没有其他技术可以解决这个问题 #include <initializer_list> // Here I want to define type and number of components for each point template <typename T, int
#include <initializer_list>
// Here I want to define type and number of components for each point
template <typename T, int DIM>
class Geometry
{
public:
void addPoint(std::initializer_list<T> coords)
{
assert(coords.size() == DIM); // Working good, but not compile-time
// Next line does not compile because size() is not known at compile-time
static_assert(coords.size() == DIM, "Wrong number of components");
}
};
#包括
//这里我想为每个点定义组件的类型和数量
模板
类几何
{
公众:
无效添加点(标准::初始值设定项\u列表坐标)
{
assert(coords.size()==DIM);//工作正常,但不是编译时
//下一行不编译,因为编译时不知道size()
静态断言(coords.size()=DIM,“组件数量错误”);
}
};
您不能静态地断言运行时数量。而初始值设定项列表中的值的数量是由函数的调用方在运行时决定的
即使使函数constexpr
也不起作用,因为函数的求值不需要在编译时进行
你应该改为使用可变模板。多亏了,我开始关注可变模板。问题不仅在于检查参数的数量,还在于检查它们的类型是否可转换为基类型。以下是我基于和主题的解决方案。它按照GCC 4.9中的预期工作
template<class T, class...>
struct are_convertible : std::true_type
{};
template<class T, class U, class... TT>
struct are_convertible<T, U, TT...>
: std::integral_constant<bool, std::is_convertible<T,U>{} && are_convertible<T, TT...>{}>
{};
template <typename T, int DIM>
class Geometry
{
public:
template<typename... Args>
void addPoint(Args... coords)
{
static_assert(sizeof...(coords) == DIM, "Number of components does not match template");
static_assert(are_convertible<T, Args...>{}, "All arguments' types must be convertible to the template type");
}
};
模板
结构是可转换的:std::true\u类型
{};
模板
结构是可转换的
:std::积分常数
{};
模板
类几何
{
公众:
模板
无效添加点(Args…coords)
{
静态断言(sizeof…(coords)=DIM,“组件数量与模板不匹配”);
static_assert(are_convertable{},“所有参数的类型必须可转换为模板类型”);
}
};
添加带有DIM数据成员的POD类点最不适合您的目的。然后隐式构造函数调用将确保一切正常 不知何故,这个问题不断浮出水面。如果您想使用初始值设定项列表语法调用addPoint
,解决方案是使用template void addPoint(const T(&coords)[N])
。然后,您可以在函数体中静态断言(N==DIM,”)
。然而,这是最近在标准草案中指定的(一年前),所以Clang还不支持它(看起来在3.8.0中会支持)。它在GCC(合理的最新版本)和Visual C++ 2015中工作。@波格丹:好的解决方案!但是,据我所见,它有一个缺点:当我尝试传递一个整数而不是像geo.addPoint({1.0,2})这样的基类型double时代码>我得到以下错误:不匹配的类型“double”和“int”
。变量模板不仅允许我检查严格的类型相等性,还允许我执行类型转换。看起来像GCC中的一个错误-它试图在不应该的时候推断元素类型。感谢您的澄清!以前从未处理过可变模板,但您的anwser激励我探索这个主题。把我的解决方案贴在下面。我不确定它是否很优雅,但它解决了问题。我不确定我理解你的意思。你能举个例子吗?std::is_convertible
检查T
是否可转换为U
,而不是相反。还要记住,初始值设定项列表禁止缩小转换范围,而此解决方案不允许。