gpt4 book ai didi

c++ - 为什么模板 不被识别为可通过模板 typename> 实例化?

转载 作者:可可西里 更新时间:2023-11-01 17:34:35 27 4
gpt4 key购买 nike

我试图任意“绑定(bind)”模板参数,但遇到了一个优雅问题。

直接切入根本问题,gcc 6.2 有以下问题,但逻辑上我认为没有问题......

template<template<typename, typename> P, typename A, typename B>
struct foo {
static constexpr bool value = P<A, B>::value;
};

template<typename...Ts>
struct bar {
static constexpr bool value = true;
};

... foo给出bar例如 foo<bar, void, void>应该导致 bar<void, void> 的实例化(这是有效的),谁是 value成员是true因此 foo<bar, void, void>::value同样是true . 有效地,这应该(在我看来)导致实例化结构在概念上类似于...

struct bar<void, void> {
static constexpr bool value = true;
};

struct foo<bar, void, void> {
static constexpr bool value = bar<void, void>::value; //which is true
};

您可以在此处查看此概念的实际应用(或错误)https://godbolt.org/g/lT9umg .

现在回到开始,首先我尝试了以下...

template<typename...>
struct type_list { };

template<template<typename...> typename Tmpl, typename...Ts>
struct bind_template {
template<typename...Us>
using type = Tmpl<Ts..., Us...>;
};

template<template<typename> typename Predicate, typename...Ts>
struct has_matching_type {
private:
template<template<typename> typename, typename, typename=void>
struct helper: std::false_type { };
template<template<typename> typename P, typename U, typename...Us>
struct helper<P, type_list<U, Us...>, typename std::enable_if<P<U>::value>::type>: std::true_type { };
template<template<typename> typename P, typename U, typename...Us>
struct helper<P, type_list<U, Us...>, typename std::enable_if<!P<U>::value>::type>: helper<P, type_list<Us...>> { };
public:
static constexpr bool value = helper<Predicate, type_list<Ts...>>::value;
};

template<typename T, typename...Ts>
using has_type = has_matching_type<bind_template<std::is_same, T>::template type, Ts...>;

稍后我可能会尝试通过 has_type<T, Ts...> 实例化如...

cout << has_type<long, int, bool, long, float>::value << endl;

然而,正如我所指出的,gcc 6.2.0 提示说因为它似乎没有认识到,一旦解析完成,模板实例化在实用上是等效的。

只需知道模板参数的数量并专门针对该确切数量即可解决问题。如果我专攻bound_template保持std::is_same<LHS, RHS>心里...

template<template<typename, typename> typename Tmpl, typename T>
struct bind_template<Tmpl, T> {
template<typename U>
using type = Tmpl<T, U>;
};

...我们突然编译并评估编译时没有问题,因为 gcc 看到 bind_template<std::is_same, long>::type完全采用一种类型参数。

显然,无论编译器如何,将这个概念抽象出来以允许任何模板参数(例如整型常量而不仅仅是类型)是一个基本问题。虽然只关注类型一分钟,但我的问题是多重的:

  1. 我是否在概念上遗漏了一些东西,而编译器实际上正在做对我来说应该显而易见的事情?
  2. 如果不是,这是否违反了 C++11 标准,不受标准指导,还是编译器依赖性?
  3. 无论前两个问题的答案如何,是否有一些优雅的方法可以解决这个问题?

在功能上,真正的问题(特别是如果这是 C++11 中不可避免的问题)是......

是否有一些优雅的方法可以抽象地绑定(bind)模板,而不必专门针对每种情况(这里最简单的是 n 种类型)?

只要能够得到问题 1 或 3 的答案就太好了。问题 3 是最重要的,因为归根结底,什么才是最重要的。

显然,我可以专攻(如上所示)。不过,一个大问题是即使以下内容似乎也不起作用(至少根据 this online compiler )...

template<template<typename...> class Tmpl, typename... Ts>
struct bind_helper {
template<typename... Us>
struct type: Tmpl<Ts..., Us...> { };
template<typename A>
struct type<A>: Tmpl<Ts..., A> { };
template<typename A, typename B>
struct type<A, B>: Tmpl<Ts..., A, B> { };
template<typename A, typename B, typename C>
struct type<A, B, C>: Tmpl<Ts..., A, B, C> { };
};

这意味着,我不仅必须生成一堆参数,而且还必须通过完整的 bind_template 来匹配外部参数。特化。这很快变成(实际上是)一个二项式问题。

进一步扩展这个概念(但仍然保持类型),我计划接下来以相同的方式实现“占位符”std::bind使用占位符(这会非常优雅地工作,因为我会在索引处剥离并重新加入列表)。显然,如果没有更抽象的方法可用,这将是一团糟。

最佳答案

这在 C++17 中得到修复。具体来说,来自 14.3.3 "Template template arguments", paragraph 3:

template<class T> class A { /* ... */ };
template<class T, class U = T> class B { /* ... */ };
template<class ... Types> class C { /* ... */ };
template<auto n> class D { /* ... */ };
template<template<class> class P> class X { /* ... */ };
template<template<class ...> class Q> class Y { /* ... */ };
template<template<int> class R> class Z { /* ... */ };

X<A> xa; // OK
X<B> xb; // OK
X<C> xc; // OK
Y<A> ya; // OK
Y<B> yb; // OK
Y<C> yc; // OK
Z<D> zd; // OK

这里的相关例子是X<C> .这在带有标志的 g++ 7 中有效 -std=c++1z .

C++14 规定上面的例子是病式的:

template<class T> class A { /∗ ... ∗/ };
template<class T, class U = T> class B { /∗ ... ∗/ };
template <class ... Types> class C { /∗ ... ∗/ };
template<template<class> class P> class X { /∗ ... ∗/ };
template<template<class ...> class Q> class Y { /∗ ... ∗/ };
X<A> xa; // OK
X<B> xb; // ill-formed: default arguments for the parameters of a template argument are ignored
X<C> xc; // ill-formed: a template parameter pack does not match a template parameter

2016 年末论文 DR: Matching of template template-arguments excludes compatible templates 发生了变化.更改应用于 this commit from November .问题已known by the committee since 1999 or before .

关于c++ - 为什么模板 <typename...> 不被识别为可通过模板 <template<typename> typename> 实例化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42048621/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com