2009-06-02 110 views
13

考慮這個簡單而毫無意義的代碼。C++仿函數和函數模板

#include <iostream> 

struct A { 
    template<int N> 
    void test() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A a; 
    a.test<1>(); 
} 

這是一個非常簡單的函數模板示例。但是,如果我想用超載的替換A::test以使其成爲仿函數?

#include <iostream> 

struct A { 
    template<int N> 
    void operator()() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A a; 
    a<1>(); // <-- error, how do I do this? 
} 

當然如果operator()把它都依賴於模板參數,編譯器可能可能推斷出模板。但我無法弄清楚用無參數函子指定模板參數的正確語法。

有沒有適當的方法來做到這一點?

顯然,這種代碼會工作,因爲它繞過了仿函數語法:

a.operator()<1>(); 

但有點違背它是一個仿函數:-P的目的。

+0

+1:在代碼混淆中使用的奇怪語法。應在http://thc.org/root/phun/unmaintain.html中提及:-) – 2012-09-14 22:12:15

回答

9

再沒有哪個 「直接」 的方式,我知道比其他:

a.operator()<1>(); 

語法。如果您打算更改代碼,那麼將模板參數移動到類中或使用(boost | tr1):: bind來創建(boost | tr1):: function對象。

24

只能調用

a.operator()<1>(); 

但不會是使用仿函數。函子需要一個非模板運算符(),因爲它們必須能夠被調用爲varname()並且這不適用於您的代碼。

使之成爲真正的仿函數改變你的代碼模板類(函子類):

#include <iostream> 

template<int N> 
struct A { 
    void operator()() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A<1> a; 
    a(); 
} 
2

您正在嘗試一個模板參數傳遞給一個對象的實例,這是據我所知不允許。您只能將模板參數傳遞給模板函數或模板對象。

a.test < 1>();和a.operator()< 1>();因爲他們是模板功能。

使用boost :: bind(檢出boost庫)來修復它。

struct A { 
    void operator()(int n) { 
     std::cout << n << std::endl; 
    } 
}; 

int main(int argc, char* argv[]) { 
    A a; 
    boost::function<void()> f = boost::bind<void>(a, 1); 
    f(); // prints 1 

    return 0; 
} 

而且你甚至不必亂用模板!

0

沒有,沒有辦法繞過它。就像你說的那樣,你必須明確地調用操作符(這違背了目的),或者編譯器必須能夠推導出模板參數。

1

你被卡住了。你有沒有考慮過像

struct A { 
    template<int N> 
    struct B 
    { 
     void operator()() 
     { std::cout << N << std::endl; } 
    }; 

    template<int N> 
    B<N> functor() {return B<N>();} 
}; 

int main() 
{ 
    A a; 
    a.functor<1>()(); 
}