代码之家  ›  专栏  ›  技术社区  ›  Ferenc Deak

C++11:可变模板演绎逻辑

  •  2
  • Ferenc Deak  · 技术社区  · 7 年前

    我有以下结构:

    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 因此 :

    some_class<void> a;
    

    some_class<> d;
    

    突然我的代码停止编译,它给了我一个错误:

    some_class<Args>::some_class(Args ...) [with Args = {}]’ cannot be 
    overloaded
     some_class(Args...) = delete;
    

    所以问题来了:我觉得我错了,我假设 some_class<> 应推断为 无效的 专业化我只是不知道为什么。能请人解释一下为什么吗 (即:空参数列表)不同于 some_class<void> ? (标准中的几行就可以了:))

    https://ideone.com/o6u0D6

    1 回复  |  直到 7 年前
        1
  •  2
  •   Community kfsone    4 年前

    void 与任何其他类型一样(准确地说,是一个不完整的类型)。这意味着它通常可以用作类型模板参数的模板参数。以您的类模板为例,这些都是完全有效的,并且 实例化:

    some_class<void>
    some_class<void, void>
    some_class<void, void, void>
    some_class<void, char, void>
    

    在第一种情况下,参数包 Args 无效的 . 在第二种情况下,它有两个要素: 无效的 . 等等

    这与实际情况大不相同 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;
    }
    

    这将输出:

    [Live example]

    我真的想不出引用标准的相关部分。可能是这样(C++11[temp.variadic]14.5.3/1):

    A. 模板参数包 是接受零个或多个模板参数的模板参数。[ 例子:

    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