首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将template< T>自动转换为template<const T>

将template< T>自动转换为template<const T>
EN

Stack Overflow用户
提问于 2015-09-25 22:24:40
回答 1查看 153关注 0票数 4

下面这篇文章主要是针对字符串视图的,T={char, const char}是主要的模板实例化目标。

cmp函数应该以类似于strcmp的方式比较视图。问题是,当char*愉快地转换为const char*时,我不知道如何让SVec<char>转换成SVec<const char>

最后一行(cout<<(cmp(rv, rvc));)不会编译。我必须显式地进行转换(cmp(SVec<const char>(rv), rvc))。它能像char*const char*那样自动实现吗?

守则(大大简化):

代码语言:javascript
复制
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 the 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));
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-09-26 00:33:55

因此,您可能要做的第一件事是使cmp成为一个Koenig运算符。

然后,我们可以在char版本和非char版本之间标记分派:

代码语言:javascript
复制
template <typename T>
class SVec {
  private:
    static T* find_end(T* in) {
      // I think while(*in)++in; would be better
      // then the end is the 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_tenable_if_t是C++14,但只是typename垃圾邮件_t-less版本的短版本。

注意,我使用的是值而不是const&:指针和size_t不值得通过引用传递。

我还将所有ctors转发到两个瓶颈中。

..。

Koenig运算符friend int cmp使用要查找的ADL。它不是模板函数,而是为每个template类实例生成的函数,这是一个重要的区别。

Koenig运算符避免了模板运算符的问题,同时允许它们随模板类型的不同而变化。这样的操作符只能通过ADL (依赖于参数的查找)找到。

然后,它根据编译时的_impl是否是char,向char过载(现在是const正确的)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32791505

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档