基于概念的模板成员函数重载

时间:2019-01-20 09:14:09

标签: c++ templates c++-concepts c++20

this snippet中显示了一个示例,该示例说明了在没有概念的情况下如何重载模板类的模板成员函数。

现在大致尝试使用概念编写类似的内容:

template <typename T>
struct Foo{
    Foo(T elem): elem_(elem) {}
    template <typename U = T>  requires Integral<U>
    int get() {
        return -1;
    }
    template <typename U = T>  requires Bool<U>
    int get() {
        return 0;
    }
    T elem_;
};

组织这种情况的两种方法是:
1.保持声明和定义在一起:这按预期工作。 Code Snippet
2.分隔声明和定义:无法编译(Code Snippet

鉴于上述情况,我有两个问题:
1.由于SFINAE最初需要template <typename T> template <typename U=T> member_fn...的原因。有没有办法用Concepts来避免这种情况来进一步简化代码?
2.如何正确区分声明和定义?

1 个答案:

答案 0 :(得分:4)

首先,模板的约束在声明和定义中必须相同(请参见[temp.over.link]/6)。否则,编译器将无法推断出哪个声明引用了定义。

因此该代码将编译:

template <typename T>
struct Foo{

  Foo(T elem): elem_(elem) {}

  template <typename U = T>  requires Integral<U>
  int get() ;

  template <typename U = T>  requires Bool<U>
  int get() ;

  T elem_;
  };

template<class T>
template<class U> requires Integral<U> 
int Foo<T>::get() {
  return -1;
  }
template<class T>
template<class U> requires Bool<U>
int Foo<T>::get()  {
  return 0;
  }

然后就不需要使用默认模板参数的概念检查延迟技巧,因为可以将约束与函数中的trailing require-clause相关联:

template <typename T>
struct Foo{

  Foo(T elem): elem_(elem) {}


  int get() requires Integral<T>;

  int get() requires Bool<T>;

  T elem_;
  };

template<class T>
int Foo<T>::get() requires Integral<T> {
  return -1;
  }

template<class T>
int Foo<T>::get() requires Bool<T> {
  return 0;
  }