我創建了一個模板類,其中建構式接收一個std::函式物件。 第一個模板引數表示該函式的回傳值。 第二個引數定義了該函式的引數型別。
#include <functional>
/Bbase
template<class R, class Arg>
class Executor {
public:
Executor(std::function<R(Arg)> function)
: mFunction(function)
{}
private:
std::function<R(Arg)> mFunction。
};
//Specialization1template<class Arg>
class Executor<void, Arg> {
public:
Executor(std::function<void(Arg)> function)
: mFunction(function)
{}
private:
std::function<void(Arg)> mFunction。
};
//Specialization2
template<class R>
class Executor<R, void> {
public:
Executor(std::function<R()> function)
: mFunction(function)
{}
private:
std::function<R()> mFunction。
};
int testBase(float value){
return 5;
}
void testSpecialization1(float value){}。
int testSpecialization2() {}。
return 22;
}
int main() {
Executor executorBase{std::function(testBase)}。
Executor executorSpecialization1{std::function(testSpecialization1)}。
//Executor<int, void> executorSpecialization2{std::function(testSpecialization2)}; // Compiles
Executor executorSpecialization2{std::function(testSpecialization2)}; //不能編譯。模板<類R,類Arg>。
}
在使用函式std::function<int()>時,見executorSpecialization2,編譯器抱怨說:
main.cpp。在函式'int main()'中。
main.cpp:55:72: 錯誤。class template引數扣減失敗。
55 | Executor executorSpecialization2{std::function(testSpecialization2)}; //不能編譯。模板<類R,類Arg>使用Base。
| ^
main.cpp:55:72: error: no matching function for call to 'Executor(std::function<int()>) '
main.cpp:7:9: note: candidate: 'template<class R, class Arg> Executor(std::function<R(Arg)>)-> Executor<R, Arg> '
7 | Executor(std::function<R(Arg) > function)
| ^~~~~~~~
main.cpp:7:9: note: template引數推導/替換失敗。
main.cpp:55:72: 注意: 候選者期待1引數,0提供
55 | Executor executorSpecialization2{std::function(testSpecialization2)}; //不能編譯。模板<類R,類Arg>使用Base。
| ^
main.cpp:5:7: note: candidate: 'template<class R, class Arg> Executor(Executor<R, Arg>)-> Executor<R, Arg> '
5 | class Executor {
| ^~~~~~~~
main.cpp:5:7: note: template引數推導/替換失敗。
main. cpp:55:72: note: 'std:: function<int()>'是not從'Executor<R, Arg>'匯出的。
55 | Executor executorSpecialization2{std::function(testSpecialization2)}; //'不編譯。模板<類R,類Arg>使用Base。
|
它嘗試使用基礎版本。但是第二個引數當然是缺失的。 如果我指定了模板引數,它就會被編譯。
那么為什么基礎模板被選為executorSpecialization2? 是否有可能在這里對void使用型別推理而不需要傳遞模板引數?
謝謝
uj5u.com熱心網友回復:
當你使用Executor這個名字而沒有明確的模板引數時,比如在Executor<int, float>中,C 通常會試圖通過類模板引數推導(或CTAD)來弄清你的意思。這個程序不看任何類模板的特殊化(部分或顯式),只看主模板。
主模板有建構式Executor(std::function<R(Arg)> function);。這足以確定R和Arg的引數型別為std::function<int(float)>和std::function<void(float)>。這只是為了確定R和Arg對于Executor來說是什么,然后適用于對專業化的正常考慮,所以第二個物件確實使用了Executor<void, Arg>專業化。
但是在看到std::function<int()>的型別時,這與std::function<R(Arg)>并不匹配,所以CTAD失敗。(盡管你可以拼出一個空的函式引數串列(void),意思和()一樣,那是一個特殊的規則,需要一個非依賴性的void型別,并不適用于一個剛好有void型別的模板引數。
但是你可以通過寫一個 "推理指南 "來協助CTAD:
template <class R>。
Executor(std::function<R()> ) -> Executor<R, void>。
除了主模板的構造器之外,還使用了扣減指南。現在一個型別為 std::function<int()> void 的引數與演繹指南相匹配,編譯器確定 R 應該是 int,并使用 Executor<int, void>,它由第二個區域專業化定義。
看看它在coliru上的作業情況.
。
uj5u.com熱心網友回復:
int(void)只有在狹窄的情況下才能作為int()使用。
像這樣改變它:
template<classR, class. Args>
class Executor
并在正文中用Args...替換Arg。
去掉R, void的特殊化。
如果你需要class Executor<void, Arg>使用class Executor<void, Args...>。
你的代碼現在可以編譯作業了。
(為什么你會得到你的錯誤:隱式生成的演繹指南只基于主要的專業化。 std::function(testSpecialization2)是std::function<int()>,這與初級專業化的任何構造器不匹配。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/316145.html
標籤:
