C++中带有鸭子输入的模板

template with duck typing in C++

本文关键字:输入 鸭子 C++      更新时间:2023-10-16

有没有办法要求模板类型具有属性?

例如:

template <typename T, typename U>
void foo()
{
    U a,b;
    bool truthiness = T()(a,b);
    if (truthiness)
        // do something
}

那么,我如何要求T定义返回特定类型的operator()(U a, U b)? 这可能吗? (我知道它在 d 中,但我不确定 c++)。

ps. 如果这里的鸭子打字是错误的,请告诉我,我相信它是正确的,但我不确定。

考虑到你的意图,你的语法是错误的。由于T是一个类型,因此T(1, 2)将使用双参数构造函数构造类型 T 的临时对象。如果你想打电话给T的接线员()

你必须
T()(1, 2);

假设通过临时工作进行呼叫,以达到您的目的。

如果T没有这样的运算符(),代码就无法编译。我实际上会说模板代码的一大好处是,只要语法有效(即您正在谈论的鸭子类型),它就可以"工作",即没有必要通过要求operator ()存在来进一步限制它。

当然,在我的示例中,这实际上可能是有意义的,因为对于T = void (*)(int, int)代码在语法上是有效的,但会导致通过空指针调用函数。但同样,这是特定于我的代码版本,我不知道您要将运算符()应用于哪种类型的T特定对象。

话虽如此,Boost 库具有相当多的功能,允许人们检查这些属性并将其用于模板元编程和/或静态断言中的分支,这是毫无价值的。

通过简单地表达模板,您需要 T 具有operator()(int, int) .如果不编译,它将无法编译。

但是,如果您正在创建一个 API 并希望通知 API 的用户他们已经传入了不兼容的类型,那么您需要创建一个检测运算符的类型特征,您可以专门化函数来区分该事实并创建一个static_assert来指示事实。

如果您有权访问 decltype,您可以相对轻松地滚动自己的支票。

template <class T, class U> class check_same_type_t;
template <class T> class check_same_type_t<T, T> { };
template <class T, class U>
void foo()
{
    U a,b;
    check_same_type_t<bool, decltype(T()(a, b))> check;
    bool truthiness = T()(a,b);
    if (truthiness) ;
        // do something
}

这将实现以下功能:

struct A {
    bool operator()(int, int) { return true; }
};
struct B {
    int operator()(int, int) { return 1; }
};
int
main()
{
    foo<A, int>(); // will compile
    foo<B, int>(); // won't compile
}

只要确保这是你真正想要的。强制通用算法使用特定类型可能会回来咬你。如果一个类型隐式转换为布尔值,为什么在你的条件下使用起来不令人满意?