this piece below supposed string view t={char, const char}
being primary intended template instantiation target.
the cmp function supposed compare views analogously strcmp
. problem while char*
happily converts const char*
don't know how svec<char>
convert svec<const char>
happily.
the last line (cout<<(cmp(rv, rvc));
) won't compile. have convertion explicitly (cmp(svec<const char>(rv), rvc)
). can automatic char*
const char*
?
the code (much simplified):
template <typename t> class svec { protected: t* begin_; size_t size_; public: svec(t* begin, size_t size) : begin_(begin), size_(size) {}; svec(t* begin, t* end) : begin_(begin), size_(end-begin) {}; svec(t* begin) : begin_(begin) { while (*(begin++)) {}; size_ = begin - 1 - begin_; } //^null element indicates end ///conversion operator svec<const t>() const { return svec<const t>(begin_, size_); } }; //general lexicographic compare template <typename t> inline int cmp(const svec<const t>& l, const svec<const t> & r){ return 1; } //char specialization template <> inline int cmp<char>(const svec<const char>& l, const svec<const char>& r){ return 1; } //explicit instantiation template int cmp<char>(const svec<const char>& l, const svec<const char>& r); #include <iostream> int main(){ using namespace std; char ar[] = "st"; svec<char> sv = ar; svec<const char> svc = "str"; cout<<(cmp(svec<const char>(sv), svc)); cout<<(cmp(sv, svc)); }
so first thing should make cmp
koenig operator.
then can tag dispatch between char , non-char versions:
template <typename t> class svec { private: static t* find_end(t* in) { // think while(*in)++in; better // end null, not one-past-the-null. while(*in++) {}; return in; } protected: t* begin_ = nullptr; size_t size_ = 0; public: svec() = default; svec(svec const&) = default; svec(t* begin, size_t size) : begin_(begin), size_(size) {}; svec(t* begin, t* end) : svec(begin, end-begin) {} svec(t* begin) : svec(begin, find_end(begin)) {} operator svec<const t>() const { return svec<const t>(begin_, size_); } friend int cmp(svec<t> l, svec<t> r) { return cmp_impl(l, r, std::is_same<std::decay_t<t>,char>{}); } private: static int cmp_impl(svec<const char> l, svec<const char> r, std::true_type){ return 1; } static int cmp_impl(svec<const t> l, svec<const t> r, std::false_type){ return 1; } };
std::decay_t
, enable_if_t
c++14, short versions of typename
spam _t
-less versions.
notice take things value instead of const&
: pointer , size_t
not merit passing reference.
i forward ctors 2 bottlenecks.
...
the koenig operator friend int cmp
uses adl found. not template function, rather function generated each template
class instance, important distinction.
koenig operators avoid problems of template operators, while allowing them vary type of template. such operator can found via adl (argument dependent lookup).
it dispatches _impl
overloads (which const-correct) based on if t
char
or not @ compile time.
Comments
Post a Comment