我正在用 C 制作一個決議器組合器。目前,我正在嘗試創建一個序列函式,該函式將按順序呼叫其他決議器并在元組中回傳所有結果。
代碼
template<typename T>
T parse(std::function<T(Stream*)> parser, Stream* stream)
{
return parser(stream);
}
std::function<char(Stream*)> Char(char c)
{
return [=](Stream* stream) -> char {
auto ch = stream->Next();
if (ch == c) {
stream->Consume(1);
return c;
}
return 0;
};
}
template <typename ...T, typename R>
std::function<R(Stream*)> Seq(T... a)
{
return [=](Stream* stream) -> R {
std::tuple tuple = { a(stream)... };
return tuple;
};
}
問題是函式 Seq 需要知道作為元組的回傳型別。這個元組由引數包內的函式的所有結果組成。所以我不知道如何告訴編譯器回傳型別是什么。
這是主要代碼。
auto& charA = Char('a');
auto& seq = Seq(Char('#'), charA);
Stream stream("text.txt");
parse(seq, &stream);
這是錯誤跟蹤。
TestLayer.cpp(338,27): error C3547: el parámetro de plantilla 'R' no se puede usar porque sigue a un paquete de parámetros de plantilla y no se puede deducir de los parámetros de funciones de 'Seq'
TestLayer.cpp(337): message : vea la declaración de 'R'
TestLayer.cpp(356,14): error C2672: 'Seq': no se encontró una función sobrecargada que coincida
TestLayer.cpp(356,14): error C2783: 'std::function<R(Stream *)> Seq(T...)': no se pudo deducir el argumento de plantilla para 'R'
TestLayer.cpp(338): message : vea la declaración de 'Seq'
TestLayer.cpp(356,12): error C2530: 'seq': se deben inicializar las referencias
TestLayer.cpp(360,11): error C3536: 'seq': no se puede usar antes de inicializarse
TestLayer.cpp(360,2): error C2672: 'parse': no se encontró una función sobrecargada que coincida
TestLayer.cpp(360,20): error C2784: 'T parse(std::function<T(Stream *)>,Stream *)': no se pudo deducir el argumento de plantilla para 'std::function<T(Stream *)>' desde 'int'
TestLayer.cpp(293): message : vea la declaración de 'parse'
編輯:
所以,感謝評論,我想出了這個解決方案:
template <typename ...T>
auto Seq(T... a) -> std::function<decltype(std::tuple{ a(std::declval<Stream*>())... })(Stream*)>
{
return [=](Stream* stream) -> decltype(std::tuple{ a(std::declval<Stream*>())... }) {
std::tuple tuple = { a(stream)... };
return tuple;
};
}
我不知道這是否是最佳解決方案。
uj5u.com熱心網友回復:
在 C 11 中,您可以弄清楚std::functionsR引數應該在不同的地方。我選擇使其成為具有默認型別的模板引數:
template<
typename... T,
class R = decltype(std::make_tuple(std::declval<T>()(std::declval<Stream*>())...))
>
auto Seq(T... a) -> std::function<R(Stream*)>
{
return [=](Stream* stream) {
return std::make_tuple(a(stream)...);
};
}
這是一個沒有額外模板引數的替代版本:
template<typename... T>
auto Seq(T... a) ->
std::function<
decltype(
std::make_tuple(std::declval<T>()(std::declval<Stream*>())...)
)(Stream*)
>
{
return [=](Stream* stream) {
return std::make_tuple(a(stream)...);
};
}
在 C 17 中,它更簡單:
template<typename... T>
auto Seq(T... a) {
return std::function([=](Stream* stream) {
return std::make_tuple(a(stream)...);
});
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/376721.html
上一篇:方法的輸入取決于模板結構
下一篇:如何簡潔地實體化多個列舉的模板?
