std::tuple
và using
là bạn bè.
Nếu bạn xác định Visitable
theo cách này
template <typename, typename>
class Visitable;
template<typename Derived, typename... Types>
class Visitable<Derived, std::tuple<Types...>> : public VisitableInterface<Types...> {
public:
virtual void accept(Visitor<Types...> &visitor) {
visitor.visit(static_cast<Derived&>(*this));
}
};
và thêm, qua using
, một cái gì đó thay thế ý tưởng vĩ mô
using tupleT = std::tuple<IntegerElement, StringElement, BoxElement, ImageElement>;
định nghĩa của các yếu tố của bạn trở nên đơn giản
class IntegerElement: public Visitable<IntegerElement, tupleT> {};
class StringElement: public Visitable<StringElement, tupleT> {};
class BoxElement: public Visitable<BoxElement, tupleT> {};
class ImageElement: public Visitable<ImageElement, tupleT> {};
Ví dụ của bạn đã sửa đổi
#include <iostream>
template<typename... Types>
class Visitor;
template<typename Type>
class Visitor<Type> {
public:
virtual void visit(Type &visitable) = 0;
};
template<typename Type, typename... Types>
class Visitor<Type, Types...>: public Visitor<Types...> {
public:
using Visitor<Types...>::visit;
virtual void visit(Type &visitable) = 0;
};
template<typename... Types>
class VisitableInterface {
public:
virtual void accept(Visitor<Types...> &visitor) = 0;
};
template <typename, typename>
class Visitable;
template<typename Derived, typename... Types>
class Visitable<Derived, std::tuple<Types...>> : public VisitableInterface<Types...> {
public:
virtual void accept(Visitor<Types...> &visitor) {
visitor.visit(static_cast<Derived&>(*this));
}
};
class IntegerElement;
class StringElement;
class BoxElement;
class ImageElement;
using tupleT = std::tuple<IntegerElement, StringElement, BoxElement, ImageElement>;
class IntegerElement: public Visitable<IntegerElement, tupleT> {};
class StringElement: public Visitable<StringElement, tupleT> {};
class BoxElement: public Visitable<BoxElement, tupleT> {};
class ImageElement: public Visitable<ImageElement, tupleT> {};
class RenderEngine : public Visitor<IntegerElement, StringElement, BoxElement, ImageElement>
{
public:
virtual void visit(IntegerElement& e) { std::cout << "visit Int\n"; };
virtual void visit(StringElement& e) { std::cout << "visit Str\n"; };
virtual void visit(BoxElement& e) { std::cout << "visit Box\n"; };
virtual void visit(ImageElement& e) { std::cout << "visit Img\n"; };
};
int main(void)
{
RenderEngine renderEngine;
IntegerElement intE;
StringElement strE;
BoxElement boxE;
ImageElement imgE;
renderEngine.visit(intE);
renderEngine.visit(strE);
renderEngine.visit(boxE);
renderEngine.visit(imgE);
return 0;
}
--- EDIT ---
tôi cố gắng để đáp ứng với comment-câu hỏi của bạn
tại sao là lớp mẫu có thể đến thăm; cần trước khi xác định mẫu thực tế?
Tôi không biết nếu nó có thể làm điều này một cách đơn giản hơn nhưng ... đó là bởi vì chúng ta cần "trích xuất" các loại từ std::tuple
. Vì vậy, bạn cần có một định nghĩa chung (template <typename, typename>
để có thể nhận được các loại std::tuple<something>
và bạn cần một chuyên môn hóa, do đó bạn có thể trích xuất các someting
loại.
lừa gọn gàng cùng cũng có thể được thực hiện cho mẫu của khách bởi định một mẫu bổ sung mà phải mất một std :: tuple như mẫu tham số. bạn có thể thêm video này vào câu trả lời của bạn là tốt, xin vui lòng?
có, đó là có thể.
Nhưng bạn phải modif y VisitableInterface
và RenderEngine
cũng vậy.
Một thay đổi lớn cho một cải tiến nhỏ (IMHO); chỉ để sử dụng tupleT
xác định RenderEngine
.
Dù sao, ví dụ của bạn trở nên
#include <iostream>
template<typename>
class Visitor;
template<typename Type>
class Visitor<std::tuple<Type>> {
public:
virtual void visit(Type &visitable) = 0;
};
template<typename Type, typename... Types>
class Visitor<std::tuple<Type, Types...>>: public Visitor<std::tuple<Types...>> {
public:
using Visitor<std::tuple<Types...>>::visit;
virtual void visit(Type &visitable) = 0;
};
template<typename... Types>
class VisitableInterface {
public:
virtual void accept(Visitor<std::tuple<Types...>> &visitor) = 0;
};
template <typename, typename>
class Visitable;
template<typename Derived, typename... Types>
class Visitable<Derived, std::tuple<Types...>> : public VisitableInterface<Types...> {
public:
virtual void accept(Visitor<std::tuple<Types...>> &visitor) {
visitor.visit(static_cast<Derived&>(*this));
}
};
class IntegerElement;
class StringElement;
class BoxElement;
class ImageElement;
using tupleT = std::tuple<IntegerElement, StringElement, BoxElement, ImageElement>;
class IntegerElement: public Visitable<IntegerElement, tupleT> {};
class StringElement: public Visitable<StringElement, tupleT> {};
class BoxElement: public Visitable<BoxElement, tupleT> {};
class ImageElement: public Visitable<ImageElement, tupleT> {};
class RenderEngine : public Visitor<tupleT>
{
public:
virtual void visit(IntegerElement& e) { std::cout << "visit Int\n"; };
virtual void visit(StringElement& e) { std::cout << "visit Str\n"; };
virtual void visit(BoxElement& e) { std::cout << "visit Box\n"; };
virtual void visit(ImageElement& e) { std::cout << "visit Img\n"; };
};
int main(void)
{
RenderEngine renderEngine;
IntegerElement intE;
StringElement strE;
BoxElement boxE;
ImageElement imgE;
renderEngine.visit(intE);
renderEngine.visit(strE);
renderEngine.visit(boxE);
renderEngine.visit(imgE);
return 0;
}
lý do xuống bầu cử là gì? – Nikopol
Tôi giả sử mã ví dụ sẽ làm cho câu hỏi tốt hơn một chút. Đôi khi sẽ dễ dàng hơn khi xem mã được đề cập. Ngoài ra nếu mã sẽ có thể biên dịch này cũng sẽ được tốt đẹp vì vậy chúng tôi có thể kiểm tra lại đối với một trình biên dịch đầu tiên mà không cần phải mã một cái gì đó mà có thể là cách bạn dự định nó. – Hayt
Okey, tôi sẽ thêm một số mã tối thiểu để làm rõ câu hỏi. Cảm ơn vì bạn đã phản hồi! :) – Nikopol