簡體   English   中英

我可以聲明一個模板以僅接受具有同類簽名的函數嗎?

[英]Can I declare a template to only accept functions with homogeneous signature?

我有一組雙重函數,每個函數接受N個類型為T的參數,第二個為X類型。

對於N=2T=intX=std::vector<int> ,二元組將如下所示:

void my_function2(int x1, int x2) {}
void my_function2(int x1, int x2, std::vector<int> other) {}

我試圖編寫一個模板化的高階函數,並將第一個函數傳遞給該函數。

這將適用於N=2

template <typename R, typename T>
int my_hof(R(*param)(T, T)) { param(1,2); }

my_hof(&my_function2); // compiles

使param簽名顯式很重要,因為否則模板實例化將由於“未解析的重載函數類型”而失敗。 關鍵是要消除my_function2()的第二次重載。

我的問題是我無法想到將其推廣到N 我嘗試使用可變參數模板:

template <typename R, typename ...X> 
struct make_signature { using type = R(*)(int, int); };
// Cheating a big on make_signature not to clutter the question
// But the idea would be to repeat the same type N times.

template <typename R, typename ...X>
int my_generalized_hof(typename make_signature<R, X...>::type param) {
    f(1,2); // cheating a bit on the call too 
}

my_generalized_hof(&my_function2); // does not compile

我猜編譯器會感到困惑,因為沒有直接給出param的類型,它無法決定使用哪個重載來進行類型計算。 (“再次出現未解析的重載函數類型”)。 我認為它也將拒絕執行類型計算,因為它無法推斷R的類型。

我想不出一種生成簽名的方法。

有可能用C ++編寫嗎?

(請注意,我知道可以通過在調用my_generalized_hof()時將my_function2()轉換為正確的類型來選擇重載,但是我想避免這種情況)

我提出以下make_signature

template <typename T, std::size_t>
using getType = T;

template <typename, typename, std::size_t N,
          typename = std::make_index_sequence<N>>
struct make_signature;

template <typename R, typename T, std::size_t N, std::size_t ... Is>
struct make_signature<R, T, N, std::index_sequence<Is...>>
 { using type = R(*)(getType<T, Is>...); };

但是有一個問題:當你寫的時候

template <typename R, typename T, std::size_t N>
void my_generalized_hof (typename make_signature<R, T, N>::type param)
 {
   // do something with param
 }

make<R, T, N>部分處於無推論上下文中(在::之前),因此無法從參數推導RTN

我的意思是...你不能打電話

 my_generalized_hof(&my_function2); 

您必須如下明確模板參數

 // ...............VVVVVVVVVVVVVVV
 my_generalized_hof<void, int, 2u>(&my_function2); 

以下是完整的編譯示例

#include <utility>
#include <vector>
#include <type_traits>

void my_function2(int x1, int x2) {}
void my_function2(int x1, int x2, std::vector<int> other) {}

template <typename T, std::size_t>
using getType = T;

template <typename, typename, std::size_t N,
          typename = std::make_index_sequence<N>>
struct make_signature;

template <typename R, typename T, std::size_t N, std::size_t ... Is>
struct make_signature<R, T, N, std::index_sequence<Is...>>
 { using type = R(*)(getType<T, Is>...); };

template <typename R, typename T, std::size_t N>
void my_generalized_hof (typename make_signature<R, T, N>::type param)
 {
   // do something with param
 }

int main ()
 {
   my_generalized_hof<void, int, 2u>(&my_function2); 
 }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM