特定模板的模板函数专门化(而不是类型)

Kla*_*aus 2 c++ templates partial-specialization c++-concepts c++20

我有一些模板化类类型,例如 A、B、C,如下所示:

template < typename T >
class A{}; 

template < typename T >
class B{}; 

template < typename T >
class C{};
Run Code Online (Sandbox Code Playgroud)

现在我想要一个函数,它通常接受任何类型,例如:

template < typename T> 
void Func()
{
    std::cout << "Default " << __PRETTY_FUNCTION__ << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

现在我想将该函数专门化为仅接受给定的模板类之一,例如:

template < typename T>
void Func<A<T>>() 
{
    std::cout << "All A Types " << __PRETTY_FUNCTION__ << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

这是不允许的,因为它只是部分专业化。好的。

我认为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>>();
}
Run Code Online (Sandbox Code Playgroud)

我感觉有点复杂。可以简化一下吗?Check如果可以删除模板就好了。任何想法?

在这里查看完整的例子

Igo*_*nik 5

一种常见的解决方法如下:

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(); }
Run Code Online (Sandbox Code Playgroud)

函数模板不能部分特化,但类模板可以;所以我们只是将前者委托给后者。


Sto*_*ica 5

我感觉有点复杂。可以简化一下吗?如果可以删除检查模板就好了。任何想法?

事实上,大部分复杂性和不优雅之处在于您需要为每个类模板提供一个新概念。编写一个通用且可重用的概念,使用起来不再复杂。

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>;
Run Code Online (Sandbox Code Playgroud)

与您的原理相同,只是检查器可与采用任意数量类型参数的模板一起使用。同时,该概念接受相同的参数。第一个参数具有特殊含义,在简写语法中隐含地理解为受约束的模板参数。其余部分(模板模板参数)必须明确给出。

如何使用?像这样

template <instantiation_of<A> T>
int Func()
{
    return 'A';
}

template <instantiation_of<B> T>
int Func()
{
    return 'B';
}
Run Code Online (Sandbox Code Playgroud)

有一个新的类模板来约束吗?没问题,这个概念无需额外的样板即可工作。

template <instantiation_of<D> T>
int Func()
{
    return 'D';
}
Run Code Online (Sandbox Code Playgroud)