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

l0oc07j2  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(217)

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

struct Error1 : public Error {}
struct Error2 : public Error {
    int a;
    Error2(int a): a(a) {};
}

template<class T> requires TheConceptIWant // don't know how to write this
void foo(T &t) {
    t.reportsError<Error1>();
    t.reportsError<Error2>(3);
}

字符串
但不包括:

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


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

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

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

struct ReportManager {
    template<class T, class... Args>
    void reportsError(Args&&... args) {
        auto error = std::unique_ptr<T>(new T(std::forward<Args>(args)...));

        // logic that handles and outputs this error to users.
    }
};

// somewhere

int main() {
    ReportManager obj;
    foo(obj);
}

0kjbasz6

0kjbasz61#

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

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

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

// synthesize a new class derived from Error
struct ErrorChild : Error {};

template <typename T>
concept ErrorReporter = requires (T &t) {
     t.template reportsError<ErrorChild>();
};


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

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


然后又道:

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

进一步说明

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


可以简化为

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

相关问题