代码之家  ›  专栏  ›  技术社区  ›  PYA

变量函数不能用clang编译

  •  3
  • PYA  · 技术社区  · 7 年前

    首先,如果这是一个副本,我很抱歉,我很乐意把它取下来,但我甚至不确定这里的问题/诊断是什么。

    无论如何,我这里的代码与gcc一起工作,而不是clang——为什么会这样?我显然不明白为什么Clang不能编译这个。

    #include <iostream>
    #include <type_traits>
    
    using std::cout;
    using std::endl;
    
    
    template <typename T, typename... Args, typename std::enable_if<!sizeof...(Args)>::type* = nullptr>
    void func(int start_size, int idx)
    {
        cout << start_size << " " << idx << endl;
        return;
    }
    
    template <typename T, typename... Args, typename std::enable_if<sizeof...(Args)>::type* = nullptr>
    void func(int start_size, int idx)
    {
    
        if((idx + 1) == int(start_size - int(sizeof...(Args))))
           {
               cout << start_size << " " << idx << endl;
               return;
           }
           func<Args...>(start_size, idx);
    }
    
    template <typename... Args>
    void func_wrapper(int idx)
    {
        func<Args...>(sizeof...(Args),idx);
    }
    
    
    int main()
    {
        func_wrapper<int,double,char>(1);
    
    }
    

    错误:

    prog.cc:37:5: error: no matching function for call to 'func'
        func<Args...>(sizeof...(Args),idx);
        ^~~~~~~~~~~~~
    prog.cc:44:5: note: in instantiation of function template specialization 'func_wrapper<int, double, char>' requested here
        func_wrapper<int,double,char>(1);
        ^
    prog.cc:16:6: note: candidate template ignored: requirement '!sizeof...(Args)' was not satisfied [with T = int, Args = <double, char>]
    void func(int start_size, int idx)
         ^
    prog.cc:23:6: note: candidate template ignored: substitution failure [with T = int, Args = <double, char>]: non-type template argument evaluates to 2, which cannot be narrowed to type 'bool'
    void func(int start_size, int idx)
         ^
    1 error generated.
    

    Wandbox: https://wandbox.org/permlink/yqki47uYcwUlE013

    2 回复  |  直到 7 年前
        1
  •  7
  •   llllllllll    7 年前

    Clang拒绝此代码是正确的。要消除错误,应显式应用转换:

    std::enable_if<bool(sizeof...(Args))>
    

    理由是:

    [temp.arg.nontype]/5

    对用作 非类型模板参数。如果非类型模板参数不能 转换为相应模板参数的类型,然后 程序格式错误。

    (5.1)对于整数或枚举的非类型模板参数 类型, 转换常量表达式中允许的转换 ([表达式常量])已应用。 .

    然后 [expr.const]/3 表示不自动考虑缩小转换:

    类型t的转换常量表达式是文本常量 表达式,隐式转换为类型t,其中 在文本常量表达式中允许转换(如果有),并且 隐式转换序列只包含用户定义的 转换,左值到右值转换([conv.lval]),整数 促销活动([conv.prom]),以及 积分转换([转换积分]) 缩小转换除外 ([dcl.init.list])

    因此,在这种情况下,从 std::size_t bool ,应明确: bool(sizeof...(Args))

        2
  •  1
  •   Jarod42    7 年前

    除了缺少的显式转换之外, std::size_t bool 这需要代码

    std::enable_if<sizeof...(Args) != 0>
    

    还有一个错误:

    temp#res-8.3

    如果出现以下情况,程序格式错误,不需要诊断:

    […]

    变量模板的每个有效专门化都需要一个空模板参数包,

    所以

    template <typename T,
              typename... Args,
              typename std::enable_if<sizeof...(Args) == 0>::type* = nullptr>
    

    无效。
    (还有) void* = nullptr 这可能有问题)。

    您可以使用2个重载来编写它:

    template <typename T>
    void func(int start_size, int idx)
    {
        cout << start_size << " " << idx << endl;
    }
    
    template <typename T, typename T2, typename... Args> // Addition of T2, and change sizeof...
    void func(int start_size, int idx)
    {
        if ((idx + 1) == int(start_size - int(1 + sizeof...(Args)))) {
            cout << start_size << " " << idx << endl;
            return;
        }
        func<T2, Args...>(start_size, idx);
    }