File tree Expand file tree Collapse file tree 3 files changed +58
-1
lines changed Expand file tree Collapse file tree 3 files changed +58
-1
lines changed Original file line number Diff line number Diff line change @@ -626,6 +626,27 @@ auto as( X const* x ) -> C const* {
626
626
return dynamic_cast <C const *>(x);
627
627
}
628
628
629
+ template <typename C, typename X>
630
+ inline constexpr auto program_violates_strict_type_safety_guarantee =
631
+ std::is_same_v<C, X>
632
+ || requires (X x){ C{x}; }
633
+ || std::is_base_of_v<C, X>
634
+ ;
635
+
636
+ template < typename C, typename T >
637
+ auto strict_as (T&& t) -> auto {
638
+ static_assert (program_violates_strict_type_safety_guarantee<C, std::remove_cvref_t <T>>, " type cannot be safely cast - consider using optional cast '?' or throwing cast" );
639
+ return cpp2::as<C>(std::forward<T>(t));
640
+ }
641
+
642
+ template < typename C, typename T >
643
+ auto optional_as (T&& t) -> auto {
644
+ try {
645
+ return std::optional<C>{cpp2::as<C>(std::forward<T>(t))};
646
+ } catch (const cpp2::narrowing_error&) {
647
+ return std::optional<C>{};
648
+ }
649
+ }
629
650
630
651
// -------------------------------------------------------------------------------------------------------------
631
652
// std::variant is and as
Original file line number Diff line number Diff line change @@ -1906,7 +1906,33 @@ class cppfront
1906
1906
return ;
1907
1907
}
1908
1908
1909
- printer.print_cpp2 (" cpp2::as<" , n.position ());
1909
+ bool add_strict_as = false ;
1910
+ bool add_optional_as = false ;
1911
+ if (auto * postfix = n.terms .front ().expr ->get_postfix_expression_node ()){
1912
+ if (auto * id_expr = std::get_if<primary_expression_node::id_expression>(&postfix->expr ->expr )) {
1913
+ if (auto * unqual = std::get_if<id_expression_node::unqualified>(&(*id_expr)->id )) {
1914
+ if ((*unqual)->strict ) {
1915
+ add_strict_as = true ;
1916
+ } else if ((*unqual)->optional ) {
1917
+ add_optional_as = true ;
1918
+ }
1919
+ } else if (auto * qual = std::get_if<id_expression_node::qualified>(&(*id_expr)->id )){
1920
+ if ((*qual)->ids .back ().id ->strict ) {
1921
+ add_strict_as = true ;
1922
+ } else if ((*qual)->ids .back ().id ->optional ) {
1923
+ add_optional_as = true ;
1924
+ }
1925
+ }
1926
+ }
1927
+ }
1928
+
1929
+ if (add_strict_as) {
1930
+ printer.print_cpp2 (" cpp2::strict_as<" , n.position ());
1931
+ } else if (add_optional_as) {
1932
+ printer.print_cpp2 (" cpp2::optional_as<" , n.position ());
1933
+ } else {
1934
+ printer.print_cpp2 (" cpp2::as<" , n.position ());
1935
+ }
1910
1936
emit (*n.terms .front ().expr );
1911
1937
printer.print_cpp2 (" >(" , n.position ());
1912
1938
Original file line number Diff line number Diff line change @@ -379,6 +379,8 @@ struct unqualified_id_node
379
379
> arg;
380
380
};
381
381
std::vector<term> template_args;
382
+ token const * strict = {}; // optional
383
+ token const * optional = {}; // optional
382
384
383
385
auto get_token () -> token const * {
384
386
if (template_args.empty ()) {
@@ -1836,6 +1838,14 @@ class parser
1836
1838
next ();
1837
1839
}
1838
1840
1841
+ if (curr ().type () == lexeme::Not) {
1842
+ n->strict = &curr ();
1843
+ next ();
1844
+ } else if (curr ().type () == lexeme::QuestionMark) {
1845
+ n->optional = &curr ();
1846
+ next ();
1847
+ }
1848
+
1839
1849
return n;
1840
1850
}
1841
1851
You can’t perform that action at this time.
0 commit comments