2015-11-05 29 views
1

有下一个代码问题不同的优先级:C++可变参数模板:在GCC和NVCC /英特尔

#include <iostream> 
#include <functional> 
using namespace std; 

template<typename... Args> 
inline double foo(function<double (Args...)> fun, Args... args) { 
    return fun(args...); 
} 

template<typename... Args, typename... ArgsTmp> 
double foo(function<double (Args...)> fun, ArgsTmp... args) { 
    return foo(fun, 1., args...); 
} 

int main() { 

    function<double (double, double, double)> fun = [&](double x, double y, double z) -> double { 
     return x+y+z; 
    }; 

    cout << foo(fun) << endl; 
} 

当我用gcc编译的一切它去罚款。但是,如果我试图编译它,例如,与英特尔或NVCC-7.5(这实际上是我的目标),我发现了以下错误:

more than one instance of overloaded function "foo" matches the argument list: 
      function template "double foo(std::vector<limits, std::allocator<limits>>, std::function<double (Args...)>, Args...)" 
      function template "double foo(std::vector<limits, std::allocator<limits>>, std::function<double (Args...)>, ArgsTmp...)" 
      argument types are: (std::vector<limits, std::allocator<limits>>, std::function<double (double, double, double)>, double, double, double) 
... 
1 error 

有没有什么办法让编译器知道明确指出当Args==ArgsTmp(在第二个模板中)foo()的下列实现应该被拒绝?

+0

我不知道这是怎么多的事情来帮助你,但代码是罚款 - 当Args和ArgsTmp完全相同时,第一个模板的专门化应该是首选的,因为根据功能模板的部分排序规则,第一个模板比第二个模板更专用。该代码在GCC 5.2.0,Clang 3.7.0和VC++ 2013和2015上运行良好。如果错误来自nvcc转发编译的主机编译器,则可能需要了解哪些版本可能会升级。 – bogdan

回答

0

您可以尝试SFINAE和enable_if

template<typename... Args, typename... ArgsTmp> 
std::enable_if_t<!std::is_same<std::tuple<Args...>, 
           std::tuple<ArgsTmp...>>::value, 
       double> 
foo(function<double (Args...)> fun, ArgsTmp... args) { 
    return foo(fun, 1., args...); 
} 
+0

谢谢。我试着花了几个小时才弄清楚如何使用SFINAE,但最终只是认为我做错了方式。虽然,我不得不改变你的代码: –

0

你可以考虑的参数个数:

#include <iostream> 
#include <functional> 
#include <type_traits> 

template<typename... Args> 
inline double foo(std::function<double (Args...)> fun, Args... args) { 
    return fun(args...); 
} 

// Only considered, if the number of arguments is less than the number 
// of expected arguments (accepting any number of arguments may lead 
// to infinite recursion). 
template<typename... Args, typename... ArgsTmp> 
inline typename std::enable_if<sizeof...(ArgsTmp) < sizeof...(Args), double>::type 
foo(std::function<double (Args...)> fun, ArgsTmp... args) { 
    return foo(fun, 1., args...); 
} 

int main() 
{ 
    // A shorter variant 
    std::function<double (double)> fun = [&](double x) -> double { 
     return x; 
    }; 
    std::cout << foo(fun) << std::endl; 
    std::cout << foo(fun, 2.0) << std::endl; 
    // error: no matching function for call to ‘foo(std::function<double(double)>&, double, double)’ 
    // std::cout << foo(fun, 3.0, 4.0) << std::endl; 
} 
+0

在我的情况下,我最好确保ArgsTmp和Args完全相同。但这也是一个有效的解决方案。 –

+0

@AlexCat:测试参数太多。 –

+0

你是什么意思?这意味着foo()的第一个调用只有一个参数:一个函数。 –