C++ 为什么可以';这个模板参数不能推导吗?
Foo的参数有默认值,因此在main()中我可以执行Foo();创建一个Foo,它将具有默认的模板参数。但是,我不能在模板参数中使用:C++ 为什么可以';这个模板参数不能推导吗?,c++,templates,C++,Templates,Foo的参数有默认值,因此在main()中我可以执行Foo();创建一个Foo,它将具有默认的模板参数。但是,我不能在模板参数中使用: template <typename T = double, int a =2, int b = 3> struct Foo {}; //cannot deduce template arguments for ‘Foo’ from () template <typename FooType = Foo()> // <--
template <typename T = double, int a =2, int b = 3>
struct Foo {};
//cannot deduce template arguments for ‘Foo’ from ()
template <typename FooType = Foo()> // <-- Error
struct TemplatedStructTakingAFooType
{
};
int main()
{
Foo(); // Foo type is deduced to be default values, ie.,
//Foo<double, 2, 3>;
decltype(Foo()); // Compiler knows the type
}
模板
结构Foo{};
//无法从()推断“Foo”的模板参数
template/问题在于Foo
不是一种类型,而是一种类型的模板
您需要在此处指定一个实际类型,该类型需要模板尖括号,Foo
,即类型Foo
:
typename FooType=Foo
Foo()
不是类型,因此需要decltype
:
typename FooType = decltype(Foo())
有些事情必须改变,因为你在混合想法
你可以通过Foo作为
类型参数
模板参数
用户定义的非类型模板参数(C++20中新增)
以下是每种方法的一个示例:
template <typename T = double, int a =2, int b = 3>
struct Foo {};
// As a type. The caller has secided what the template arguments that Foo
// will have, or by allowing them to default, has chosen the defaults.
template <typename FooType = decltype(Foo{})>
struct A
{
};
// Here FooType is passed as a template. Inside B, you'd need to
// provide it template parameters to instantiate it.
template <template <typename T, int, int> typename Foo2 = Foo>
struct B
{
using F = Foo2<float, 3, 4>;
};
// As a user-defined non-type template parameter
// This only works in C++20, since it's a new feature
template <Foo f>
struct C
{
};
// And finally, CTAD to with deduced arguments for Foo as a user-defined
// non-type tempalte parameter, with friendly constructor syntax. (For the
// caller, not for the reader of this monstrosity).
// The deduction guide allows passing an instance of Foo<T, a, b> to the
// constructor and allowing it to match types for T, a, b for the struct.
template <typename T, int a, int b, Foo<T, a, b> f>
struct D
{
D(Foo<T, a, b>) { }
};
template <typename T, int a, int b> D(Foo<T, a, b>) -> D<T, a, b, Foo<T, a, b>{}>;
int main()
{
A a; // default
A<Foo<float, 5, 9>> a2; // give types to Foo given to A
B<Foo> b; // Pass Foo to b as a template-template param
C<Foo{}> c; // Pass instance of Foo with default args
Foo<short, 99, 0> customFoo;
D d(customFoo); // Pass instance to constructor(!) to
// set template args even when Foo is not default.
}
模板
结构Foo{};
//作为一种类型。调用者已隔离了Foo所使用的模板参数
//将具有,或通过允许它们默认,已选择默认值。
模板
结构A
{
};
//这里FooType作为模板传递。在B里面,你需要
//提供it模板参数以对其进行实例化。
模板
结构B
{
使用F=Foo2;
};
//作为用户定义的非类型模板参数
//这只适用于C++20,因为它是一个新特性
模板
结构C
{
};
//最后,CTAD使用用户定义的Foo的推断参数
//非类型tempalte参数,具有友好的构造函数语法。(对于
//呼叫者,而不是这个怪物的读者)。
//《扣减指南》允许将Foo实例传递给
//构造函数,并允许它为结构匹配T、a、b的类型。
模板
结构D
{
D(Foo){}
};
模板D(Foo)->D;
int main()
{
A;//默认值
A a2;//给Foo类型给A
B;//将Foo作为模板参数传递给B
C;//使用默认参数传递Foo的实例
Foo customFoo;
D D(customFoo);//将实例传递给构造函数(!)以
//即使Foo不是默认值,也要设置模板参数。
}
现场观看:@Someprogrammerdude仍然不能在OnlineGDB上工作,我将尝试获取链接:template
works@JerryJeremiah这里面的括号在做什么?我会理解的,但是Foo()
?很明显,它确实有效,但我不明白它是如何起作用的。@JerryJeremiah谢谢你让我走上正轨的!:)@Zebrafish Foo()是一个不带参数并返回Foo的函数,int()是一个不带参数并返回int的函数。这两种函数都是类型,只是不是您要查找的类型。因此,您可以使用Foo或decltype(Foo()),如下面的答案所示。这是有道理的。我犯了一个愚蠢的错误,使用了typename FooType=Foo(),但是decltype也不起作用@Zebrafish:它确实起作用。您正在使用哪个编译器??试试更高的version@Zebrafishgcc11应该没问题tried@nhatnq位于的代码(与先前注释中位于onlinegdb.com/HxujYBmcc的代码相同)可以工作,但我不知道为什么它得到的结果与您的不同。@Zebrafish此错误来自编译器。无论如何,它在后来的版本中被修正了,因为它解释了“Foo不是一个类型,它是一个类型的模板”,这是完全有道理的。顺便说一句,Jerry Jeremiah的解决方案我不明白,他也没有解释,在'Foo()'中不是一种类型,这就像做typename IntType=int(),这也很奇怪,即使int()不是一种类型。@Zebrafishint()
是一种类型(函数没有参数返回int
).int()既是类型又是表达式。在这种情况下,选择类型
template <typename T = double, int a =2, int b = 3>
struct Foo {};
// As a type. The caller has secided what the template arguments that Foo
// will have, or by allowing them to default, has chosen the defaults.
template <typename FooType = decltype(Foo{})>
struct A
{
};
// Here FooType is passed as a template. Inside B, you'd need to
// provide it template parameters to instantiate it.
template <template <typename T, int, int> typename Foo2 = Foo>
struct B
{
using F = Foo2<float, 3, 4>;
};
// As a user-defined non-type template parameter
// This only works in C++20, since it's a new feature
template <Foo f>
struct C
{
};
// And finally, CTAD to with deduced arguments for Foo as a user-defined
// non-type tempalte parameter, with friendly constructor syntax. (For the
// caller, not for the reader of this monstrosity).
// The deduction guide allows passing an instance of Foo<T, a, b> to the
// constructor and allowing it to match types for T, a, b for the struct.
template <typename T, int a, int b, Foo<T, a, b> f>
struct D
{
D(Foo<T, a, b>) { }
};
template <typename T, int a, int b> D(Foo<T, a, b>) -> D<T, a, b, Foo<T, a, b>{}>;
int main()
{
A a; // default
A<Foo<float, 5, 9>> a2; // give types to Foo given to A
B<Foo> b; // Pass Foo to b as a template-template param
C<Foo{}> c; // Pass instance of Foo with default args
Foo<short, 99, 0> customFoo;
D d(customFoo); // Pass instance to constructor(!) to
// set template args even when Foo is not default.
}