我有以下结构:
template <class... Args>
class some_class
{
public:
some_class() = default;
some_class(Args...) = delete;
~some_class() = default;
};
template<>
class some_class<void>
{
public:
some_class() = default;
~some_class() = default;
};
原因是我只想让用户使用默认构造函数创建对象,例如:
some_class<int,float> b;
应该可以工作但是
some_class<int,float> c(1,3.4);
应该给我一个编译错误。
在某些时候我还需要根据void
创建模板,因此void
的专业化:
some_class<void> a;
但是我错误地输入了:
some_class<> d;
突然我的代码停止编译,它给了我错误:
some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be
overloaded
some_class(Args...) = delete;
所以问题出现了:我觉得我错了,我认为some_class<>
应该推导到void
专业化......我只是不知道为什么。可以请某人解释为什么some_class<>
(即:空参数列表)与some_class<void>
不同? (标准中的几行会做:))
答案 0 :(得分:2)
void
类似于任何其他类型(确切地说是不完整类型)。这意味着它通常可以用作类型模板参数的模板参数。使用您的类模板,这些都是完全有效的, distinct,实例化:
some_class<void>
some_class<void, void>
some_class<void, void, void>
some_class<void, char, void>
在第一种情况下,参数包Args
有一个元素:void
。在第二种情况下,它有两个元素:void
和void
。等等。
这与案例some_class<>
完全不同,在这种情况下,参数包具有零元素。您可以使用sizeof...
:
template <class... Pack>
struct Sizer
{
static constexpr size_t size = sizeof...(Pack);
};
int main()
{
std::cout << Sizer<>::size << ' ' << Sizer<void>::size << ' ' << Sizer<void, void>::size << std::endl;
}
这将输出:
0 1 2
我无法真正想到引用标准的相关部分。也许这个(C ++ 11 [temp.variadic] 14.5.3 / 1):
模板参数包是一个模板参数,可接受零个或多个模板参数。 [示例:
template<class ... Types> struct Tuple { }; Tuple<> t0; // Types contains no arguments Tuple<int> t1; // Types contains one argument: int Tuple<int, float> t2; // Types contains two arguments: int and float Tuple<0> error; // error: 0 is not a type
- 示例]