3

Java and I guess C#(and others) support Bounded Type Parameters which lets us restrict what types may be used in template classes/functions.

I am curious if there is a reason, official or otherwise, for not adding native support for bounded types to C++? Anything to do with how templates are currently processed? Multiple inheritance issues?

I would expect it to be quite useful.

4

4 回答 4

1

一个简单的事实是,这不存在的原因是没有人想出一个可以让它在没有可怕副作用的情况下工作的功能。委员会已经在这个问题上工作了十年或更长时间,而最新的迭代仍然不适合目的。

此外,您所指的通用限制根本不是有界类型。他们支持的唯一界限是“X 继承自 Y”,从本质上讲,坦率地说,SFINAEstd::is_base_of很好地涵盖了这种情况。C++ 需要更强大的东西才能有用,因为运行时继承是最没用的特性之一。

于 2013-08-11T03:46:32.437 回答
1

C++ 有 SFINAE,可以通过 std::enable_if 相当容易地利用它。结合 type_traits 实际上,IMO 比 Java 和 C# 拥有的有界类型更强大。通过一些工作,您还可以制作一些不错的 constexpr 函数来为您测试这些东西。将它与一些宏结合起来,你就有了一些看起来有点像它的东西

#include <iostream>
#include <type_traits>

#define ENABLE_IF typename std::enable_if<
#define THEN(T) ,T>::type

class foo {};
class bar : public foo {};

template<class T, class U>
constexpr bool extends() {
    return std::is_base_of<
        typename std::remove_reference<U>::type, 
        typename std::remove_reference<T>::type
    >::value;
}

template<class T>
ENABLE_IF extends<T, foo>() THEN(void) test(T&& v) {
    std::cout << "T extends foo!!";
}

int main() {
    test(bar{});
}

现在我不确定我是否会重新开始,但这是可行的,到目前为止,除了 SFINAE 难以调试之外,我认为这样做没有任何问题

于 2013-08-11T03:58:11.623 回答
0

大多数时候,对模板参数的约束应该是类型,而是模板需要的操作。C++ 以一种有点尴尬的方式做到这一点,仅仅是因为如果模板使用的操作不存在,您会收到一条错误消息。例如:

template <class T>
void show(T t) {
    std::cout << t << std::endl;
}

如果您使用未实现的类型调用此模板函数,operator<<则会收到错误消息。Java 方法是使用print方法定义接口,并要求用户传递实现该接口的类型的对象。C++ 方法不需要所有这些机制。

在 C++ 中这样做的问题在于,您可能会收到非常混乱的错误消息。缺少的操作通常用于另一个模板的某些低级部分,并且错误消息与您编写的代码没有明确的关系。这是概念背后的驱动力之一:模板的作者可以设置它使用的操作,并且传递一个类型不支持这些操作的对象将导致在接口处违反概念,而不是在内部实现,因此您可能会收到更有用的错误消息。

于 2013-08-11T13:42:11.347 回答
0

有界类型参数的目的是在提供的类型和所需的基类不匹配的情况下引发编译时错误,因此这在 C++11 及更高版本中很容易实现,static_assert并提供给它的值std::is_base_of如下:

template <typename T>
class C {
    static_assert(std::is_base_of<SomeBoundedBaseClass, T>::value, "Bounded type parameter violation!");
    //...the rest of the class C
};

SomeBoundedBaseClass您要将类型参数绑定T到其后代或完全匹配的类在哪里。

另请注意,通过这种方式,您可以提及任何要显示为编译错误的自定义消息,因此它甚至比 Java 的内置功能更具优势。不用说 C++ 更冗长,但它也提供了更多的自由。

于 2020-05-23T14:20:59.843 回答