繁体   English   中英

特定模板的模板 function 专业化(非类型)

[英]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是否可以绑定到某个可推导出Uconst A<U>&类型的参数。 你可以在这里看到这个例子: https://godbolt.org/z/dTEbaaPvh

这读起来并不令人愉快。 如果您将多次使用此 hack,我认为最好只定义特征。 我回答你的问题只是为了满足你的好奇心,而不是推荐这种技术。

上面的版本不仅会在模板参数是某个A<U>时选择受约束的版本,而且还会在它可能是 cv-qualified、可能是 ref-qualified 以及可能从A<U>公开派生时选择受约束的版本。 可以进行一些调整以使约束更加严格。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM