diff --git a/src/languages/c-like.js b/src/languages/c-like.js index cfc040c7fb..57a204e0a1 100644 --- a/src/languages/c-like.js +++ b/src/languages/c-like.js @@ -105,6 +105,7 @@ export default function(hljs) { 'atomic_bool atomic_char atomic_schar ' + 'atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong ' + 'atomic_ullong new throw return ' + + 'class struct' + 'and and_eq bitand bitor compl not not_eq or or_eq xor xor_eq', built_in: 'std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream ' + 'auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set ' + @@ -200,6 +201,67 @@ export default function(hljs) { ] }; + var TEMPLATE_USE = { + begin: /{;]/, + keywords: CPP_KEYWORDS, + contains: EXPRESSION_CONTAINS.concat([ + // Match left-shift to prevent it from creating a nested `TEMPLATE_USE`. + { begin: /</ } + // TEMPLATE_USE + ] + }, + 'self' + ]) + }; + + var CLASS_DECLARATION = { + className: 'class', + beginKeywords: 'class struct union', end: /[{;:]/, + contains: [ + { beginKeywords: "final" }, + TEMPLATE_USE, + TITLE_MODE + ] + }; + + var TEMPLATE_DECLARATION = { + begin: /template\s* void f();` + end: /[>;{]/, + keywords: CPP_KEYWORDS, + contains: EXPRESSION_CONTAINS.concat([ + // Match left-shift to prevent it from creating a nested `TEMPLATE_USE`. + { begin: /</ }, + TEMPLATE_USE + ] + }, + 'self' + ]), + relevance: 10 + }; + return { aliases: ['c', 'cc', 'h', 'c++', 'h++', 'hpp', 'hh', 'hxx', 'cxx'], keywords: CPP_KEYWORDS, @@ -222,15 +284,8 @@ export default function(hljs) { begin: hljs.IDENT_RE + '::', keywords: CPP_KEYWORDS }, - { - className: 'class', - beginKeywords: 'class struct', end: /[{;:]/, - contains: [ - { beginKeywords: "final" }, - {begin: //, contains: ['self']}, // skip generic stuff - hljs.TITLE_MODE - ] - } + TEMPLATE_DECLARATION, + CLASS_DECLARATION, ]), exports: { preprocessor: PREPROCESSOR, diff --git a/test/markup/cpp/templates.expect.txt b/test/markup/cpp/templates.expect.txt new file mode 100644 index 0000000000..d8b03f5dbb --- /dev/null +++ b/test/markup/cpp/templates.expect.txt @@ -0,0 +1,108 @@ +template <template <typename X> class T> void f(); + +template class A::B<1, 2> {}; + +template void A::f(int); + +template <class T, std::size_t N = sizeof(T), class K = T> +ostream& operator<< (ostream& os, const skg::Triplet<T> pt) ; +void other_stuff_that_isnt_colored(); + + +template<class T> +class My_vector { /* ... */ }; + +template<class T = void> +struct My_op_functor { /* ... */ }; + +template<typename... Ts> +class My_tuple { /* ... */ }; + + +template<class> class My_vector; +template<class = void> struct My_op_functor; +template<typename...> class My_tuple; + + +template<typename T> concept C1 = true; +template<typename... Ts> concept C2 = true; // variadic concept +template<typename T, typename U> concept C3 = true; + +template<C1 T> struct s1; // constraint-expression is C1<T> +template<C1... T> struct s2; // constraint-expression is (C1<T> && ...) +template<C2... T> struct s3; // constraint-expression is (C2<T> && ...) +template<C3<int> T> struct s4; // constraint-expression is C3<T, int> +template<C3<int>... T> struct s5; // constraint-expression is (C3<T, int> && ...) + + +template<typename K, typename V, template<typename> typename C = my_array> +class Map {}; + + +template<class B> +template<class C> +void A<B>::g(C) {} + + +void g() { + f<int()>(); +} + + +template<int (&pa)[5]> struct W {}; +template<void (*pf)(int)> struct A {}; + + +template<class T, const char* p> class X {}; + + +template<typename T> class A { int x; }; // primary template +template<typename T> class A<T*> { long x; }; // partial specialization + + +template<typename T> struct eval; // primary template + +template<template<typename, typename...> class TT, typename T1, typename... Rest> +struct eval<TT<T1, Rest...>> {}; // partial specialization of eval + + +eval<A<int>> eA; +eval<B<int, float>> eB; +eval<C<17>> eC; +eval<D<int, 17>> eD; +eval<E<int, float>> eE; + + +template <template <auto> class> void FA(); // note: C++17 + + +template<template<typename TT = char> class T> +void A<T>::g() +{ + T<> t; // ok: t is T<char> +} + +s.template foo<T>(); +class C; + + +// Hard mode + +template <int a, int b, bool c = (a > b), class T> void f1(); +template <int a, int b, bool c = (a >> b), class T> void f2(); + +template <int a, int b, bool c = (a < b), class T> void g1(); +class C; + +template <int a, int b, bool c = a < b, class T> void g1(); +class D; + +template <int a, int b, bool c = (a << b), class T> void g2(); +class E; + +template <int a, int b, bool c = a << b, class T> void g2(); +class F; + +template <int A = (B<C>), class T> class C; +template <int A = B<(c > D<E>)>, class T> class C; +template <int A = B<(c > D<(e > f)>)>, class T> class C; diff --git a/test/markup/cpp/templates.txt b/test/markup/cpp/templates.txt new file mode 100644 index 0000000000..0ecaff024f --- /dev/null +++ b/test/markup/cpp/templates.txt @@ -0,0 +1,108 @@ +template