C++模板自动推导失败,无法推导模板参数。

7

我希望更好地理解自动模板推导(在使用g++ -std=c++17编译时应用)在main()中的前三行有效,但第四行失败的原因。是否有可能在不久的将来被编译器接受?

template <typename P = void>
class A {
public:
    void f1() {}
};

template<typename C>
void g() {}


int main() {
    A<> a;       // works
    A aa;        // works
    g<A<>>();    // works
    g<A>();      // fails
    return 0;
}

5
A 不是一种类型,而是一个用于类型的模板。 - Algirdas Preidžius
没有什么可以推断的。A指的是模板,而不是实例化。 - 463035818_is_not_a_number
3
我认为这里的主要问题是为什么 A a 可以工作,但 g<A> 不能。这当然符合标准,但你很难说服任何人它是直观的(当然,C++并没有在这方面努力)。 - Max Langhof
2个回答

4

只是签名的问题。基本上,您正在传递错误类型。

A a A <> a 都表示您想要具有默认模板参数值的A的实例,即,您最终得到A<void>

函数g< C >()接受一个模板参数,该参数恰好是一种类型,而不是另一个模板化类型。当您使用A<>调用它时,告诉编译器您想要使用“模板类型A的实例化”,这是有效的。当您使用A调用它时,告诉编译器您想要使用 C为模板类型来调用g< C >(),但是它不符合其签名。

如果您这样声明/定义 g() template <typename <typename> TTemplatedType> g(),它将接受以下调用 g< A >(),但是 g< A<> >() 将失败,因为现在它不再想要除模板化类型之外的其他东西。


3
我认为你的最后一段是不必要的。问题是关于 A ag<A> 之间的(或多或少意外的)差异。事实上,在第一个例子中,AA<> 都被接受,但在第二个例子中突然出现了“A 是模板而不是类型”的情况(如果这是原因,为什么第一次可以工作?)。我知道这是符合标准的正确做法,C++ 并不试图非常直观,但你的最后一句话可能显得有些轻蔑。 - Max Langhof
@MaxLanghof,明白了。感谢你向我报告你的想法和感受。 - mister why

3

在 C++17 中,当类模板的名称被用作正在构造的对象的类型时,也会执行模板参数推导。

对于模板内部的显式类型,没有任何变化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接