可变参数函数不会用clang编译

时间:2018-10-03 03:08:55

标签: c++ c++11 templates language-lawyer

首先,我很抱歉这是重复的,我很乐意将其删除,但是我什至不确定这里的问题/诊断是什么。

无论如何,我的代码在这里适用于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.

魔盒:https://wandbox.org/permlink/yqki47uYcwUlE013

2 个答案:

答案 0 :(得分:7)

clang拒绝此代码是正确的。要消除该错误,您应该明确应用转换:

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

原因是:

[temp.arg.nontype]/5

  

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

     

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

然后[expr.const]/3说,缩小转换不会被自动考虑:

  

类型T的转换常量表达式是文字常量   表达式,隐式转换为类型T,其中隐式   文字常量表达式中允许进行转换(如果有),并且   隐式转换序列仅包含用户定义的   转换,左值到右值转换([conv.lval]),整数   促销([conv.prom])和整体转化([conv.integral])   除了缩小转换范围([dcl.init.list])

因此,在这种情况下,从std::size_tbool的转换范围越来越小,应该明确指出:bool(sizeof...(Args))

答案 1 :(得分:1)

除了缺少从numpy.testing.assert_allclosestd::size_t的显式转换外,这将需要以下代码:

bool

还有另一个错误:

temp#res-8.3

  

该程序格式不正确,无需进行诊断,如果:

     

[..]

     

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

所以

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

无效。
(还有template <typename T, typename... Args, typename std::enable_if<sizeof...(Args) == 0>::type* = nullptr> 可能有问题)。

您可以编写2个重载来代替它:

void* = nullptr