检查子类型时的专用方法模板
Specializing method template while checking for subtype
在检查是否存在某些子类型的同时,为方法专用化模板的语法是什么?
// Syntax works fine for functions
template<class T, class... Assertions> void my_function();
template <class list_t, class list_t::value_type>
void my_function() { }
// Doesn't work for methods
class MyClass {
template<class T, class... Assertions> void my_method();
};
// Commenting out the next two lines results in successful compile
template <class list_t, class list_t::value_type>
void MyClass::my_method() { }
int main() { }
叮当给我:
out-of-line definition of 'my_method' does not match any declaration in 'MyClass'
您在这里既不专门介绍模板方法,也不专门介绍函数。您只是重载免费模板函数并尝试以奇怪的方式重载该方法。要使其正常工作,您应该使用标记调度(因为部分函数模板专用化在C++中是不可能的(或constexpr if
如果您的编译器支持 C++17
专用化语法如下:
// dummy list_t...
struct list_t
{
using value_type = int;
};
// standard implementation:
template<class T, class... Assertions>
void my_function() { }
// specialization
template <>
void my_function<list_t, list_t::value_type>() { }
class MyClass
{
template<class T, class... Assertions>
void my_method();
};
// standard implementation:
template<class T, class... Assertions>
void MyClass::my_method() { }
// specialisation
template <>
void MyClass::my_method<list_t, list_t::value_type>() { }
我不清楚你到底想要什么。
如果您希望仅在T
是类/结构且其中value_type
类型时才实现该my_method()
,并且您希望在使用没有value_type
的T
调用时出现编译错误,我建议通过declval()
和decltype()
使用 SFINAE
。作为
template <typename T>
auto my_method ()
-> decltype( std::declval<typename T::value_type>(), void() )
{ }
如果可以使用 C++17 代替decltype( std::declval<typename T::value_type>(), void() )
,则可以使用std::void_t<T::value_type>
。
如果你想要一个具有更通用版本和带有value_type
的类/结构的专用版本的my_method()
,我建议开发一个泛型my_method()
,只需调用另一个方法my_method_helper()
添加一个int
值
template <typename T>
void my_method ()
{ my_method_helper<T>(0); }
并将 SFINAE 和函数重my_method_helper()
载与接收long
(因此不完全是int
(的my_method_helper()
相结合,并为更通用的版本启用
template <typename T>
void my_method_helper (long)
{ }
以及完全接收int
的版本(因此最好在可用时优于long
版本(,但仅在T
包含value_type
时才启用。
template <typename T>
auto my_method_helper (int)
-> decltype( std::declval<typename T::value_type>(), void() )
{ }
因此,当T
包含value_type
时调用my_method_helper(int)
,否则调用my_method_helper(long)
。
下面是一个完整的编译示例(方法名称已更改(
#include <utility>
#include <iostream>
struct MyClass
{
template <typename T>
auto method_1 ()
-> decltype( std::declval<typename T::value_type>(), void() )
{ std::cout << "method_1 " << std::endl; }
template <typename T>
auto method_2 (int)
-> decltype( std::declval<typename T::value_type>(), void() )
{ std::cout << "method_2 specialized" << std::endl; }
template <typename T>
void method_2 (long)
{ std::cout << "method_2 generic" << std::endl; }
template <typename T>
void method_2 ()
{ method_2<T>(0); }
};
struct foo
{ using value_type = int; };
int main()
{
MyClass mc;
mc.method_1<foo>();
// mc.method_1<int>(); // compilation error
mc.method_2<foo>(); // call specialized version
mc.method_2<int>(); // call generic version
}
部分题外话:我不明白"语法适用于函数"是什么意思
template<class T, class... Assertions> void my_function();
template <class list_t, class list_t::value_type>
void my_function() { }
你怎么称呼my_function()
?
- 检查子类型时的专用方法模板
- 部分方法专用化
- 基于枚举参数调用专用模板方法
- 类中一种方法的部分专用化
- 从非模板类调用专用模板方法
- 使用类指针重载C++命名空间函数模板专用化替代方法?
- 没有针对完全专用模板类的外联虚拟方法定义
- 从部分专用模板方法调用模板非静态方法
- 添加具有模板专用化的方法
- 常量字符*的模板方法专用化
- C++隐式/显式模板方法专用化问题
- enable_if在类声明之外实现的方法专用化
- 类模板:为什么我不能将单一方法专用于空类型?
- 混合显式类专用化和类方法专用化
- 显式模板专用化不能具有存储类 - 成员方法专用化
- 不完整类型(类方法专用化)的使用无效
- 显式模板函数和方法专用化
- *nix 上的模板方法专用化
- "Faking" 具有enable_if的模板类方法专用化
- 用于多种类型的模板方法专用化