从具有auto参数的模板类继承时的基类不明确

时间:2019-10-10 09:09:40

标签: c++

给出代码

#include <type_traits>

template <auto I, class T>
struct C {};

template <auto I, class T>
void func(C<I, T> c)  {}

struct C2 : C<0, int>, C<0u, long> {};

int main() {
    static_assert(!std::is_same<C<0, int>, C<0u, long>>::value);

    C2 c2;
    func<0>(c2);  // Error

    return 0;
}

我收到了错误消息(来自GCC):

<source>:15:15: note:   'C<0, T>' is an ambiguous base class of 'C2'
   15 |     func<0>(c2);
      |               ^

当实例化(C<I, T>C<0, int>)是明显不同的类型时,类模板(C<0u, long>)为何会成为模棱两可的基类?

编辑:我忘了部分专业化。

2 个答案:

答案 0 :(得分:2)

错误消息可能会稍微好一些。但是问题在于尝试进行重载解析。理论上可以从import random player_decision = input("Do you want to roll the Dice ? Type y or n: ").lower() if player_decision == "y": game_on = True else: game_on = False print("Thanks for your time!!") while game_on is True: print("Welcome") roll_dice = input("Press R to roll the dice or Q to quit the game ").upper() if roll_dice == "R": def rolling(): outcome = random.randint(1, 7) print(outcome) rolling() 合成两个可能的重载:

C2

这是因为可以将类类型的自变量与接受其基数之一的模板进行匹配。模板参数推导能够推导基类的模板参数。

但是这里有一个问题:编译器只允许从模板合成一个重载,那么应该使用哪个基类进行合成?那是模棱两可的,因此会发生您的错误。编译器不知道应该使用哪个基类来进行void func(C<0, int> c) {} void func(C<0u, long> c) {} 专业化的模板参数推导。从这个意义上说,这些基础是模棱两可的。


您的编辑没有太大变化。您指定了C,但仍可以与0参数匹配。为了匹配非类型模板参数,相应的模板参数必须是参数类型的转换后的常量表达式。 0u是一个常量表达式,可以将其转换为0常量表达式,反之亦然。因此,将0u或什至0指定为显式参数并不能解决歧义。

指定0uint将解决歧义。这样我们可以重写:

long

然后致电

template <class T, auto I>
void func(C<I, T> )  {}

答案 1 :(得分:1)

  

当实例化(C<I, T>C<0, int>)是明显不同的类型时,类模板(C<0u, long>)为何会成为模棱两可的基类?

它们是不同类型的事实是问题所在。 C2继承自两者,并且模板func接受两个基类-编译器应选择哪个基类?

您可以明确知道将c2的哪一部分传递给func时可以解决此问题:

func(static_cast<C<0, int>>(c2));  // Works fine now