2012-04-25 208 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