2012-04-25 133 views
2
// some arbitrary function 
template<typename T> 
void log(T&& obj) 
{ 
    std::cout << obj << std::endl;  
} 

// arbitrary transformation 
template<typename T> 
T convert(T&& obj) { 
    return obj; 
} 

template<template <typename> typename F, typename... T> 
void callOn(F<T> func, /// issue: what's the type of func?     
      T&&... params) 
{ 
    func(std::forward<T>(convert(std::forward<T>(params)))...); 
} 

int main() 
{ 
    callOn(log, -1, -2.0);  
    return 0; 
} 

这可能吗?解压模板模板函数的可变参数?

编译器抱怨:没有匹配的函数调用'callOn(,..>)。为什么?

更新:假设日志是不是一元函数

template<typename T> 
void log(T&& value) { std::cout << value << std::endl; } 

template<typename First, typename... Rest> 
void log(First&& f, Rest&&... rest) 
{ 
    std::cout << f << ","; 
    log(std::forward<Rest>(rest)...); 
} 

卡隆需要键入“模板”不匹配的日志类型?如何指定func的类型?

+2

元元程序设计?我们必须更深入! – 2012-04-25 18:15:03

+0

疯狂猜测:你有没有试过'模板 typename F'? – Philipp 2012-04-25 18:26:55

+0

@Philipp:这也是我的想法,但这个问题没有多大意义,因为'callOn(log,-1,-2.0);'会尝试将两个参数传递给'log',它是一元的。 – ildjarn 2012-04-25 18:32:04

回答

2

使用函数对象。这里有一个编译例如:

#include <utility> 
#include <iostream> 

struct Log 
{ 
    template<typename T> void operator()(T&& t) { 
     std::cout << t << std::endl; 
    } 

    template<typename T, typename... Rest> void operator()(T&& t, Rest&&... rest) 
    { 
     std::cout << t << ", "; 
     (*this)(std::forward<Rest>(rest)...); 
    } 
}; 

template<typename T> 
T convert(T&& obj) { 
    return obj; 
} 

template<typename F, typename... T> 
void callOn(F funcobj, T&&... params) 
{ 
    funcobj(std::forward<T>(convert(std::forward<T>(params)))...); 
} 

int main() 
{ 
    callOn(Log(), -1, -2.17, "abc"); 
    return 0; 
} 
+0

内部'std :: forward'(将调用封装为'convert')不需要,并且如果意图使'convert'的某些重载执行特殊操作,可能会产生干扰。 – 2012-04-26 06:46:24

1

我不认为template <typename> typename F语法是正确的,标准14.3.3/1指定了“A模板参数模板的模板参数应的名称类模板或别名模板“,而不是函数模板。如果你想通过一个函数模板,你可以声明参数为函数指针:

template<typename... T> 
void callOn(void (*func)(T&&...params), 
      T&&... params) 
{ 
    //same as before 
} 

callOn(log, -1, -2.0);叫的T类型不是从log但是从{-1,-2.0推导}为{int,double},那么func将从指向log<int, double>(int&&, double&&)的指针初始化。

+0

是否有可能将函数指针表示为std :: function? – 2012-04-26 12:34:14

+0

void(* func)(T && ...)工作,但std :: function func不。编译器抱怨说,它无法通过转换为类型'std :: function ''解析重载的函数'log''' – 2012-04-26 14:30:50

+0

''您正确的是'template typename F'不正确,但是你的理由是错误的 - 'template class F'确实是有效的,它只需要使用模板仿函数而不是函数模板。 – ildjarn 2012-04-26 17:04:37