2013-05-21 124 views
1

海蘭@所有, 模板轉換失敗,我們必須實現以下functioncall: 與lambda函數

std::mt19937 engine; 
color_table lut = create_random_color_map(engine); 



發動機具有可更換的。我們試圖實現這種方式:
* .HPP

#include <tuple> 
#include <random> 

typedef std::tuple<unsigned char,unsigned char,unsigned char> rgb_tuple; 

class color_table{ 
    public: 
     [...] 
     void generate(rgb_tuple predicate(const unsigned char& index)); 





}; 
template <class RANDOM> 
static rgb_tuple random_color(RANDOM engine){ 
    std::uniform_int_distribution<int> dist1 (0,255); 
    unsigned char red = (unsigned char) dist1(); 
    unsigned char green = (unsigned char) dist1(engine); 
    unsigned char blue = (unsigned char) dist1(engine); 
    return std::make_tuple(red, green, blue); 
} 

template <class RANDOM> 
static color_table create_random_color_map(RANDOM engine){ 
    color_table lut; 
    lut.generate([&](const unsigned char& i)->rgb_tuple { 
     return random_color<decltype(engine)>(engine); 
    }); 
    return lut; 
} 

* 的.cpp

... 
void color_table::generate(rgb_tuple predicate(const unsigned char& index)){ 
    for(int i = 0; i < 256; ++i){ 
     std::tie(red_table[i], green_table[i], blue_table[i]) = predicate(i); 
    } 
} 

當我們嘗試編譯,出現以下錯誤:

錯誤C2664:'color_table :: generate':將參數1 從 'create_random_color_map ::' 爲 'rgb_tuple(__cdecl *)(const的無符號字符&)' 不可能1>
沒有用戶定義convertionoperator可用,可以執行 皈依或操作者可以不被調用。 ... 函數模板「color_table create_random_color_map(RANDOM)」。與[
RANDOM =的std :: mt19937]

我們是完全無能,失敗和谷歌是不是我們在這種情況下的朋友! :/

我們感謝任何幫助!

問候 希密爾

回答

3

第一(主要)問題:

你的功能generate()接受函數指針作爲它的參數,而你試圖通過捕獲拉姆達。不幸的是,捕獲lambdas不能隱式轉換爲函數指針。每一段的C++ 11標準的5.1.2/6:

沒有λ-捕獲該閉合類型爲λ-表達具有公共非虛擬非顯式const的 將函數轉換爲具有與封閉類型的函數調用運算符相同的參數和返回類型的函數指針。此轉換函數返回的值應爲函數 的地址,該函數在調用時具有與調用閉包類型的函數調用操作符相同的效果。

你可以改變你的設計,讓generate()成爲一個函數模板,接受一個可調用對象作爲它的參數:

class color_table{ 
    public: 
     template<typename P> 
     void generate(P predicate); 
}; 

或者,你可以使用一個std::function包裝,以實現靈活性,而不重複到模板(但也有一些運行時的開銷):

#include <functional> // <== NEEDED FOR std::function 

class color_table{ 
    public: 
     void generate(std::function<rgb_tuple(const unsigned char&)> predicate); 
}; 

這裏是一個live example,顯示您的代碼與上述方案編制。

二(未成年人)的問題:

你不應該random_color()明確指定模板參數。而是讓編譯器完成其工作,並執行類型推演:

lut.generate([&](const unsigned char& i)->rgb_tuple { 
    return random_color(engine); 
//   ^^^^^^^^^^^^^^^^^^^^^ 
}); 
+0

它的工作原理!給你! – Hymir

+0

@Hymir:很高興幫助:) –

0

我覺得現在的問題是,您:

void generate(rgb_tuple predicate(const unsigned char& index)); 

應該是:

void generate(rgb_tuple (*predicate)(const unsigned char& index)); 

不能繞過功能!只是指向功能。

但唉! lambdas只能轉換爲指針函數,如果它們具有空捕捉集,並且您的lambda不能。

所以,你可以用std::function嘗試:

void generate(std::function<rgb_tuple(const unsigned char& index)> predicate); 

PS:解釋有一點是爲了......你的錯誤信息是:

從「create_random_color_map參數1的皈依: :」到 'rgb_tuple(__cdecl *)(const的無符號字符&)' 不可能

第一部分create_random_color_map::是VC++告訴你的方式,它不知道它試圖轉換的對象的類型,但它是create_random_color_map的本地對象:這顯然是lambda本身。

第二部分rgb_tuple (__cdecl *)(const unsigned char &)僅僅是一個指針到適當的類型的功能。

和誤差表示,所述第一不能轉換到後者。