c++ - Autoconverting template< T> to template<const T> -


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