0

有一个A带有模板参数的模板类Tf如果T是整数类型,我希望这个类有一个方法。该类A还有很多其他方法,所以我不想专门化整体A。我知道这个问题可以使用继承来解决,但我的问题是关于概念和要求。

这段代码

  template <typename T>
  struct A {
    void f();
  };

  template <>
  void A<int>::f() {}

按我的预期工作。它仅对类型进行f实现int。如果我尝试调用A<std::string>{}.f();它会按预期生成链接器错误。但如果我写

  template <typename T>
  struct A {
    void f();
  };

  template <std::integral T>
  void A<T>::f() {}

任何一个

  template <typename T> requires std::is_integral_v<T>
  void A<T>::f() {}

该方法f是为所有类型生成的,因此调用A<std::string>{}.f();不会给出任何错误。


这也有效

  template <typename T>
  struct A {
    void f() {}
  };

  template <>
  void A<std::string>::f() = delete;

但是这个

  template <typename T>
  struct A {
    void f() {}
  };

  template <std::integral T>
  struct A<T>::f() = delete;

给出编译错误,即重新定义f.


PS似乎根本不允许这样的构造,而g++只是忽略了方法定义中的概念f

4

2 回答 2

0

您必须添加一个新的模板参数,该参数将默认为T您可以添加您的约束std::integral<>。这里用gcc10.3.0和clang12.0.0编译,其他版本需要自己测试。

编码:

#include <concepts>
#include <string>

template <typename T>
struct A
{
    template <typename U = T>
    requires std::integral<U>
    void f();
};

template <typename T>
template <typename U>
requires std::integral<U>
void A<T>::f()
{

}

int main()
{
    A<int> a;
    a.f();

    A<std::string> s;  // This works
    // s.f();  // Compilation error: constraint not satisfied
    return 0;
}
于 2021-10-15T18:06:05.113 回答
0

四种将约束应用于函数的语法方法。

  1. 在模板参数列表中键入约束;template< Concept TypeID >.
  2. 模板参数列表后的Requires 子句;template< class TypeID > requires constexpr-andor-requires-expression.
  3. 在缩写函数模板中对 auto 的约束;void f(Concept auto id);.
  4. 函数声明后的Requires 子句;template< class TypeID > void f() requires constexpr-andor-requires-expression.

您要约束的函数没有模板参数列表,因此您不能使用方法1和2。方法3本质上是生成模板参数。这样就剩下方法4了。

#include <concepts>

template< class T >
struct A {
    void f() { /* do something */ }
    void g() requires std::integral<T> { /* do something */ }
    void h() requires std::integral<T>;
    template< std::integral U = T >
    void i() { /* do something */ }
};

template< class T >
void A<T>::h() requires std::integral<T> { /* do something */ }


int main() {
    A<double> dblA;
    dblA.f();
    // dblA.g();        // A<double>::g() is not declared or defined
    // dblA.h();        // A<double>::h() is not declared or defined
    // dblA.i();        // A<double>::h<double>() is not declared or defined
    dblA.i<int>();      // A<double>::h<int>() is declared and defined

    A<int> intA;
    intA.f();
    intA.g();           // A<int>::g() is declared and defined
    intA.h();           // A<int>::h() is declared and defined
    intA.i();           // A<int>::h<int>() is not declared and defined
    //intA.i<double>(); // A<int>::h<double>() is not declared or defined

    return 0;
}
于 2021-12-08T22:28:36.397 回答