如何编写一个C++概念来约束对象的模板化方法?

l0oc07j2  于 2024-01-09  发布在  其他
关注(0)|答案(1)|浏览(266)

我想写一个概念,描述任何对象,有一个模板化的方法称为reportsError。该方法有一个模板参数T是从Error类派生(在源代码中定义的地方),可以接受任何数量的参数。函数reportsError的实现内部将这些数据转发到std::make_unique创建一个新的错误。
例如,下面的代码应该编译:

  1. struct Error1 : public Error {}
  2. struct Error2 : public Error {
  3. int a;
  4. Error2(int a): a(a) {};
  5. }
  6. template<class T> requires TheConceptIWant // don't know how to write this
  7. void foo(T &t) {
  8. t.reportsError<Error1>();
  9. t.reportsError<Error2>(3);
  10. }

字符串
但不包括:

  1. template<class T> requires TheConceptIWant // don't know how to write this
  2. void foo(T &t) {
  3. t.reportsError<int>(0); // int is not a subclass of Error.
  4. }


我不知道怎么写,如果你知道,请写下你的答案。非常感谢!

  • 传递给函数foo的对象不需要是Error的子类!它是TEMPLATE PARAMETER ON THE METHOD必须是!*

下面是一个示例对象,我希望它可以传递给函数foo,(实际上可能无法成功编译):

  1. struct ReportManager {
  2. template<class T, class... Args>
  3. void reportsError(Args&&... args) {
  4. auto error = std::unique_ptr<T>(new T(std::forward<Args>(args)...));
  5. // logic that handles and outputs this error to users.
  6. }
  7. };
  8. // somewhere
  9. int main() {
  10. ReportManager obj;
  11. foo(obj);
  12. }

0kjbasz6

0kjbasz61#

如果约束放在reportsError上,而不是foo上,那么你要做的事情相对容易:

  1. template<std::derived_from<Error> E, typename... Args>
  2. requires std::constructible_from<E, Args...>
  3. void reportsError(Args &&...args);

字符串
现在,如果用户显式地提供E,则仅对Error的派生类型满足约束。
为“上一层”定义一个完美的概念是不可能的。概念只能验证某些表达式是格式良好的,而不能验证高级属性,如
此成员函数模板的所有专门化都是可变的,用于构造给定的E参数
你能写的最好的是:

  1. // synthesize a new class derived from Error
  2. struct ErrorChild : Error {};
  3. template <typename T>
  4. concept ErrorReporter = requires (T &t) {
  5. t.template reportsError<ErrorChild>();
  6. };


然而,没有办法验证reportsError是可变的,你最多只能强行将其增加到一定的数量。

  1. t.template reportsError<ErrorChild>();
  2. t.template reportsError<ErrorChild>(1);
  3. t.template reportsError<ErrorChild>(1, 2);
  4. // ...


然后又道:

  1. template<ErrorReporter T>
  2. void foo(T &t);

进一步说明

  1. auto error = std::unique_ptr<T>(new T(std::forward<Args>(args)...));


可以简化为

  1. auto error = std::make_unique<T>(std::forward<Args>(args)...);

展开查看全部

相关问题