Để thực hiện một số nhiệm vụ đệ quy tại địa phương tôi sử dụng phương pháp sau đây để tạo ra combinator điểm cố định tại chỗ:Fixed điểm combinator và rõ ràng kết quả loại
#include <utility>
#include <list>
#include <memory>
#include <iostream>
int main()
{
struct tree
{
int payload;
std::list<tree> children = {}; // std::list of incomplete type is allowed
};
std::size_t indent = 0;
// indication of result type here is essential
const auto print = [&] (const auto & self, const tree & node) -> void
{
std::cout << std::string(indent, ' ') << node.payload << '\n';
++indent;
for (const tree & t : node.children) {
self(self, t);
}
--indent;
};
print(print, {1, {{2, {{8}}}, {3, {{5, {{7}}}, {6}}}, {4}}});
}
Nó hoạt động tốt và in:
1
2
8
3
5
7
6
4
Nhưng nếu tôi xóa loại kết quả được chỉ định rõ ràng -> void
, thì tôi nhận được lỗi biên dịch (GCC 8):
prog.cc: In instantiation of 'main():: [with auto:1 = main()::]':
prog.cc:24:64: required from here
prog.cc:20:17: error: use of 'main():: [with auto:1 = main()::]' before deduction of 'auto'
self(self, t);
(clang 7):
prog.cc:20:13: error: function 'operator()<(lambda at prog.cc:15:24)>' with deduced return type cannot be used before it is defined
self(self, t); ^
prog.cc:24:10: note: in instantiation of function template specialization 'main()::(anonymous class)::operator()<(lambda at prog.cc:15:24)>' requested here
print(print, {1, {{2, {{8}}}, {3, {{5, {{7}}}, {6}}}, {4}}}); ^
prog.cc:15:24: note: 'operator()<(lambda at prog.cc:15:24)>' declared here
const auto print = [&] (const auto & self, const tree & node) ^
1 error generated.
Nguyên nhân gây ra lỗi là gì? Tôi nghĩ rằng trình biên dịch có thể suy ra loại kết quả nhìn vào cơ thể chức năng. Loại kết quả không phụ thuộc vào loại tham số "mẫu" self
.
Loại 'in' là một lớp đơn giản với mẫu' toán tử() '. Lớp tôi có thể vượt qua đây và ở đó. – Orient
Tôi có nên hiểu 'print.operator()' là thực thể trong biểu thức 'self (self, t)'? – Orient
@Orient Vâng, tôi có nghĩa là toán tử '()' là thực thể có kiểu chúng ta đang xác định. – Barry