我有以下模板化方法:
auto clusters = std::vector<std::pair<std::vector<long>, math::Vector3f>>
template<class T>
void eraserFunction(std::vector<T>& array, std::function<int(const T&, const T&)> func)
{
}
我有一個看起來像的功能
auto comp1 = [&](
const std::pair<std::vector<long>, math::Vector3f>& n1,
const std::pair<std::vector<long>, math::Vector3f>& n2
) -> int {
return 0;
};
math::eraserFunction(clusters, comp1);
但是,我收到一個語法錯誤說:
116 | void eraserFunction(std::vector<T>& array, std::function<int(const T&, const T&)> func)
| ^~~~~~~~~~~~~~
core.hpp:116:6: note: template argument deduction/substitution failed:
geom.cpp:593:23: note: 'math::method(const at::Tensor&, const at::Tensor&, int, float, int, int, float)::<lambda(const std::pair<std::vector<long int>, Eigen::Matrix<float, 3, 1> >&, const std::pair<std::vector<long int>, Eigen::Matrix<float, 3, 1> >&)>' is not derived from 'std::function<int(const T&, const T&)>'
593 | math::eraserFunction(clusters, comp1);
uj5u.com熱心網友回復:
函式呼叫嘗試T從第一個和第二個函式引數中進行推斷。
它將正確地T從第一個引數推匯出來,但無法從第二個引數推匯出它,因為第二個函式引數是 lambda 型別,而不是std::function型別。
如果無法從推匯出的背景關系的所有引數中進行推導,則推導失敗。
您實際上并不需要從第二個引數/引數中扣除,因為T應該完全由第一個引數確定。因此,您可以使第二個引數成為非推導背景關系,例如使用std::type_identity:
void eraserFunction(std::vector<T>& array, std::type_identity_t<std::function<int(const T&, const T&)>> func)
這需要 C 20,但如果您僅限于 C 11,也可以在用戶代碼中輕松實作:
template<typename T>
struct type_identity { using type = T; };
然后
void eraserFunction(std::vector<T>& array, typename type_identity<std::function<int(const T&, const T&)>>::type func)
std::identity_type_t<T>是 的型別別名std::identity_type<T>::type。留給范圍決議運算子的所有::內容都是非推導背景關系,這就是它起作用的原因。
如果您沒有任何特別的理由在std::function這里使用,您也可以將任何可呼叫型別作為第二個模板引數:
template<class T, class F>
void eraserFunction(std::vector<T>& array, F func)
這可以使用 lambda、函式指標std::function等作為引數呼叫。如果引數不能使用預期的型別呼叫,則會在實體化包含呼叫的函式體時導致錯誤。您可以使用 SFINAE 或自 C 20 以來的型別約束在多載決議時強制執行此操作。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/435296.html
