[英]Template function specialization for specific template ( not type )
我有一些模板化的 class 类型,例如 A、B、C,如下所示:
template < typename T >
class A{};
template < typename T >
class B{};
template < typename T >
class C{};
现在我想要一个 function 通常接受任何类型,例如:
template < typename T>
void Func()
{
std::cout << "Default " << __PRETTY_FUNCTION__ << std::endl;
}
现在我想专门化 function 以仅接受给定模板类之一,例如:
template < typename T>
void Func<A<T>>()
{
std::cout << "All A Types " << __PRETTY_FUNCTION__ << std::endl;
}
这是不允许的,因为它只是部分专业化。 好的。
我认为concept
可能会有所帮助,但感觉我想得太复杂了。 我的解决方案是:
template < typename T, template <typename > typename OUTER >
bool Check;
template < typename INNER, template < typename > typename OUTER, template < typename> typename T>
constexpr bool Check< T<INNER>, OUTER > = std::is_same_v< OUTER<INNER>, T<INNER>>;
template < typename T >
concept IsA = Check< T, A >;
template < typename T >
concept IsB = Check< T, B >;
template < IsA T >
void Func()
{
std::cout << "All A Types " << __PRETTY_FUNCTION__ << std::endl;
}
template < IsB T >
void Func()
{
std::cout << "All B Types " << __PRETTY_FUNCTION__ << std::endl;
}
int main()
{
Func<A<int>>();
Func<B<int>>();
Func<C<int>>();
}
我觉得有点复杂。 可以简化吗? 如果可以删除Check
模板会很好。 任何想法?
在此处实时查看完整示例
一种常见的解决方法是 go ,如下所示:
template <typename T>
struct FuncImpl {
static void Run() { std::cout << "Default"; }
};
template <typename T>
struct FuncImpl<A<T>> {
static void Run() { std::cout << "Specialized for A<T>"; }
};
template <typename T>
void Func() { FuncImpl<T>::Run(); }
Function 模板不能部分特化,但 class 模板可以; 所以我们只是将前者委托给后者。
我觉得有点复杂。 可以简化吗? 如果可以删除检查模板会很好。 任何想法?
事实上,您需要为每个 class 模板提供一个新概念。 写一个通用的、可复用的概念,使用起来不再复杂。
template <typename T, template <typename...> class TT>
constexpr bool is_instantiation_of_v = false;
template <template <typename...> class TT, typename... TS>
constexpr bool is_instantiation_of_v <TT<TS...>, TT> = true;
template <class C, template<typename...> class TT>
concept instantiation_of = is_instantiation_of_v<C, TT>;
与您的原理相同,除了检查器可用于采用任意数量的 arguments 类型的模板。 同时,该概念接受相同的参数。 第一个参数有特殊含义,隐式理解为简写语法中的约束模板参数。 rest(模板模板参数)必须明确给出。
如何使用? 像这样
template <instantiation_of<A> T>
int Func()
{
return 'A';
}
template <instantiation_of<B> T>
int Func()
{
return 'B';
}
有一个新的 class 模板来约束吗? 没问题,这个概念不需要额外的样板就可以工作。
template <instantiation_of<D> T>
int Func()
{
return 'D';
}
OP写道:
是的,如果可能的话,直接在函数模板参数中编写一些“即时”代码会很好......
通常,要确定它是否是某个给定 class 模板的特化,我们会提前定义一个特征,然后检查该类型是否满足该特征。 如果你不想提前定义任何东西,你必须找到一种方法来执行模板参数推导inline ,这样你就可以检查它是否成功。 在 C++20 中,这很简单,但有点难看:
template <typename T>
void Func()
{
std::cout << "unconstrained" << std::endl;
}
template <typename T>
requires requires {
[]<typename U>(const A<U>&){}(std::declval<T>());
}
void Func()
{
std::cout << "constrained" << std::endl;
}
在这里, requires 子句检查T
是否可以绑定到某个可推导出U
的const A<U>&
类型的参数。 你可以在这里看到这个例子: https://godbolt.org/z/dTEbaaPvh
这读起来并不令人愉快。 如果您将多次使用此 hack,我认为最好只定义特征。 我回答你的问题只是为了满足你的好奇心,而不是推荐这种技术。
上面的版本不仅会在模板参数是某个A<U>
时选择受约束的版本,而且还会在它可能是 cv-qualified、可能是 ref-qualified 以及可能从A<U>
公开派生时选择受约束的版本。 可以进行一些调整以使约束更加严格。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.