![](/img/trans.png)
[英]template type deduction in a member function of a templated class
[英]template static function template class type deduction
我想在单调模板类中创建静态函数,这样就可以扣除模板类的类型。 问题是,从模板类调用静态函数需要显式类型。 我想出的唯一解决方法是模板函数,而不是模板成员函数。
这是一个例子。 问题是 foo4 部分不起作用
template <class T>
class Foo
{
private:
Foo() {}
Foo(const Foo&) = delete;
Foo& operator= (const Foo&) = delete;
public:
static auto& Instance()
{
static Foo foo{};
return foo;
}
template<class K> static
auto& DeductInstance(const K&)
{
static Foo<K> foo{};
return foo;
}
};
template<class K>
auto& DeductInstance(const K&)
{
return Foo<K>::Instance();
}
void main()
{
auto& foo1 = Foo<int>::Instance(); //OK
auto& foo2 = Foo<int>::Instance(); //OK (return same example as foo1)
auto& foo3 = DeductInstance(123); //OK
auto& foo4 = Foo::DeductInstance(123); //NOT WORKING
}
从理论上讲,您可以使用注入的类名来请求语法。 这会使Foo::
解析为特定的,不相关的Foo<x>::
。 这是一个例子:
struct BaseFoo {
template<class K> static
auto& DeductInstance(const K&);
};
template <class T>
struct Foo {
static auto& Instance() {
static Foo foo{};
return foo;
}
};
template<>
struct Foo<void> : private BaseFoo {
using BaseFoo::DeductInstance;
};
template<typename K>
auto& BaseFoo::DeductInstance(const K&)
{
return Foo<K>::Instance();
}
using MakeFooAvailable = Foo<void>;
struct Dummy : MakeFooAvailable {
auto& bar() {
// Syntax working
return Foo::DeductInstance(234);
}
};
在Dummy
类中,为基类Foo
注入了一个类名,将其解析为Foo<void>
。 然后, Foo<void>
使BaseFoo::DeductInstance
在其范围内可用于名称解析。
我建议不要使用此解决方案,因为它是一个聪明的解决方案。 聪明通常意味着令人惊讶。 程序员不希望将Foo
视为非模板。 我认为最好的解决方案是:
auto& foo1 = Foo<int>::Instance(); //OK
越简单越好。
我必须承认,我不完全理解您要做什么。 但是,您可以执行以下两个操作之一:
struct foo {
template <typename T>
static T deduce(const T& t) {
return {};
}
};
template <typename T>
T deduce_free(const T& t) {
return {};
}
int main() {
auto x = foo::deduce(1);
auto y = deduce_free(1);
}
但是,在知道T
是什么之前,您无法在bar<T>
某些实例上调用方法(是否为静态)。
事情已经改变,与C ++ 17位具有类模板参数推导 ,但
据我知道这个工程的建设者,所以你仍然需要一个
我对此没有经验,所以说不出什么错;)。 foo<int>
第一之前,你可以调用一个
foo<int>::deduce()
现在是 2021 年,我们有 CTAD,但我认为它没有帮助。 我认为这非常接近你(和我!)想要的:
// A helper struct to provide Foo with a default template
// that isn't useful for instantiation:
struct DoNotInstantiate { DoNotInstantiate() = delete; };
template <class T = DoNotInstantiate>
class Foo
{
private:
Foo() {
static_assert(!std::is_same_v<T, DoNotInstantiate>, "You can't actually instantiate it with the default, it's just to make the static function work."); // Optional
}
// ...
public:
// ...
template<class K> static
auto& DeductInstance(const K&)
{
static Foo<K> foo{};
return foo;
}
};
所以你可以调用Foo<>::DeduceInstance(bar);
. 您仍然必须编写<>
但除此之外,我认为它是完美的。
如果您不希望那样并且真的希望能够在模板上调用静态,仅命名模板名称,则可以使用以下方法:
template <template<typename ...> class FooType, typename T>
auto DeduceInstance(const T& x) {
return FooType<T>::DeduceInstance(x);
}
这让您可以调用DeduceInstance<Foo>(x)
,其中Foo
只是一个模板。 但这感觉是圆的。 我更喜欢Foo<>::DeduceInstance(x);
.
如果 CTAD 让你写就好了
template <class T>
Foo::DeductInstance(const T&) -> T&;
或者它可能是
template <class T>
Foo::DeductInstance(const T&) -> Foo<T>::DeduceInstance(const T&);
或类似的东西,基本上是说如果您使用没有类型的模板名称来调用静态,请使用参数列表来掺杂调用者正在谈论的模板。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.