为什么带约束的模板模板参数需要更严格的参数?

时间:2013-12-30 22:52:44

标签: c++ templates constraints c++14

N3580描述了以下情形:

template<Object T, template<Object> Cont>
struct stack {
    Cont<T> container;
};

template<Object>
struct my_vector;

template<Regular>
struct my_list;

template<typename>
struct my_magic;

此处RegularObject的细化;也就是说,每个Regular都是 Object但不是每个Object都是Regular

我希望类型系统能够使stack<X, Y>有效, X必须是ObjectY必须可以使用Object进行实例化。这个 意味着stack<int, my_vector>stack<int, my_magic>有效, 虽然stack<int, my_list>不是。与正常功能的情况非常相似:

struct Base {};
struct Derived : Base {};

void foo(Base* p, function<void(Base*)> fun) {
    fun(p);
}

template<typename T>
void bar(T*);

我希望如果pBase*,那么foo(p, bar<Base>)foo(p, bar<void>)是有效的,而foo(p, bar<Derived>)则不是;毕竟,一个 Base*隐式转换为void*,但未转换为Derived*

但就模板而言,情况正好相反。只要 允许stack<int, my_vector>stack<int, my_list>,禁止stack<int, my_magic>。为什么是这样? my_magic适用于任何类型, 而my_list可能会失败,具体取决于我给它的对象。而且,我可以 平凡地使my_magic仅使用对象:

template<Object T>
struct my_restricted_magic : my_magic<T> {};

现在my_restricted_magic可以与stack一起使用。另一方面,有 没有简单的方法来制作一个接受任何类型的my_list,但这是完全正确的 什么传递它作为模板模板参数现在允许。

我是否误解了模板模板参数的约束目的 参数Δ

2 个答案:

答案 0 :(得分:9)

这是提案中的错误。约束模板模板参数应接受具有较弱约束的参数。

答案 1 :(得分:1)

这是猜想,但这似乎是一个可能的解释:

允许传递更具体的模板,而不是更通用的模板,是规则目前在可变参数模板模板参数方面的工作方式。您可以传递一个单类型参数模板,其中需要一个可变参数:

template<template<typename...> class> struct Foo {};
template<typename> Bar {};

Foo<Bar>(); // legal

但反之亦然:

template<template<typename> class> struct Foo {};
template<typename...> Bar {};

Foo<Bar>(); // error, argument/parameter mismatch.

措辞起源于N2555,要求允许这样的代码:

template<typename>
struct Foo;

template<template<typename...> class Fun, template... Args>
struct Foo<Fun<Args...>> {};

Foo<std::pair<int, double>>();

基本上,不是template<typename...> class是对用户的保证,而是用户必须提供明智的参数。鉴于这种涉及专业化的用法,这似乎是合理的。

这并不能解释为什么不允许传递更通用的模板,但是在N3580中反转短语会使两个规则放在一起而不是直观。

提案链接:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2555.pdf