【问题标题】:Is this nested template base class ambiguous?这个嵌套模板基类是否有歧义?
【发布时间】:2017-04-29 03:00:39
【问题描述】:

此代码用于在 Clang 3.8 中编译,在 VS 2017 中仍可编译,但在 Clang 3.9 中开始发出错误。

template <typename D, typename ... I>
struct impl : I ...
{};

template <typename D, typename ... I>
void f(impl<D, I...> const&)
{}

struct A : impl<A> {};
struct B : impl<B, A> {};

int main()
{
    f(A());
    f(B()); // Error
}

Clang 3.9 说

<source>:15:5: error: no matching function for call to 'f'
    f(B());
    ^
<source>:6:6: note: candidate template ignored: failed template argument deduction
void f(impl<D, I...> const&)
     ^

所有三个编译器都在运行: https://godbolt.org/g/OKFpPl

我希望f(A()) 推断D = A, I... = &lt;&gt;f(B()) 推断D = B, I... = A,然后可以将其推断为impl 的一个实例。我的最终目标是检测impl 的参数包中的类型,它们本身就是impl 的实例。我是不是走错了路?

【问题讨论】:

标签: c++ templates variadic-templates crtp template-argument-deduction


【解决方案1】:

不确定但是...

您的B 类继承自impl&lt;B, A&gt;,后者继承自impl&lt;A&gt;

所以B 继承自几个不同的impl&lt;D, I...&gt; 基类,所以类型推导是不明确的(D == BI... == &lt;A&gt;D == AI... == &lt;&gt;)。

所以我认为clang 3.8是错的,3.9是对的。

我的最终目标是检测 impl 参数包中的类型,它们本身就是 impl 的实例。我是不是走错了路?

是的,你做错了(我认为)。

【讨论】:

  • 是的,我怀疑 Clang 3.8 和 3.9 之间的区别在于一致性收紧。但我的标准语还不够强,无法完全确定。另外,因为无论如何这都是 CRTP,我记得在我的确切情况下,我知道第一个模板参数,这让我能够消除歧义。但我仍然对核心语言问题感到好奇。 :) 例如,其中一种类型扣除需要“转换为基础”才能匹配,而另一种则不需要。这不是更好的匹配吗?
  • @RyanShepherd - 不幸的是,我的标准语言太弱了,无法回答您的问题。而且我尝试“检测 impl 参数包中本身就是 impl 实例的类型”,但我发现问题太复杂了。关于“转base”,如果参考f()函数的调用,两个调用都需要转base;问题是第二个获得了对两个不同碱基的转换。
猜你喜欢
  • 2021-12-17
  • 1970-01-01
  • 2023-03-29
  • 2010-09-08
  • 1970-01-01
  • 2017-09-28
  • 2012-05-25
  • 1970-01-01
相关资源
最近更新 更多