Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用类模板专门化创建别名模板的专门化?_C++_C++17_Template Specialization - Fatal编程技术网

C++ 如何使用类模板专门化创建别名模板的专门化?

C++ 如何使用类模板专门化创建别名模板的专门化?,c++,c++17,template-specialization,C++,C++17,Template Specialization,我一直在使用指向数据成员的指针和指向成员函数的指针,我正在尝试创建一个模板,该模板将使用函数的类类型和返回类型或数据成员的类型创建一个专门的std::map 因此: 模板 使用Index=std::map; 结构Foo{int x;char*get_name();}; 指数indexOnX;//标准::地图 索引indexOnGetName;//标准::地图 我已经成功地编写了两个别名模板来实现这一点,但遗憾的是,它们有不同的名称: 包括 #包括 /** *将指向成员函数类型的指针拆分为其类和

我一直在使用指向数据成员的指针和指向成员函数的指针,我正在尝试创建一个模板,该模板将使用函数的类类型和返回类型或数据成员的类型创建一个专门的std::map

因此:

模板
使用Index=std::map;
结构Foo{int x;char*get_name();};
指数indexOnX;//标准::地图
索引indexOnGetName;//标准::地图
我已经成功地编写了两个别名模板来实现这一点,但遗憾的是,它们有不同的名称:

包括
#包括
/**
*将指向成员函数类型的指针拆分为其类和返回类型。
*这仅适用于不带参数的成员函数。
*/
模板
结构分解\成员\函数\指针{
//我们将实现隐藏在details结构中。类的用户不应使用这些。
结构细节{
//此模板化函数将用于将M拆分为其组件。
模板
静态T获取返回类型(T(C::*v)();
模板
静态C get_类类型(T(C::*v)();
}; 
使用return_type=decltype(details::get_returntype(std::declval());
使用type=decltype(details::get_classtype(std::declval());
};
模板
使用分解\成员\函数\指针\ t=typename分解\成员\函数\指针::type;
模板
使用分解\成员\函数\指针\ rt=typename分解\成员\函数\指针::返回\类型;
模板
结构分解\成员\对象\指针{
结构细节{
模板
静态T get_returntype(tc::*v);
模板
静态C get_类类型(tc::*v);
}; 
使用return_type=decltype(details::get_returntype(std::declval());
使用type=decltype(details::get_classtype(std::declval());
};
模板
使用decompose_member_object_pointer_t=typename decompose_member_object_pointer::type;
模板
使用decompose\u member\u object\u pointer\u rt=typename decompose\u member\u object\u pointer::return\u type;
模板
使用IndexOnMFP=std::map<
分解成员函数指针,
分解成员函数指针;
模板
使用IndexOnMOP=std::map<
分解\u成员\u对象\u指针\u rt,
分解成员对象指针;
//现在尝试使用这些别名模板
结构MyClass
{
字符值;
int age();
int age2()常量;
};
IndexOnMOP indexOnValue;
指数MFP指数年龄;
我希望能够将IndexOnMOP和IndexOnMFP组合成一个模板别名,例如IndexOnMemberPointer。我理解只有函数和类模板才允许专门化。到目前为止,我所有的尝试都失败了


作为后续工作,我还希望能够支持从指向常量成员函数的指针计算类型。

我想您可能只需要:

template <class >
struct trait;

template <class C, class T>
struct trait<T C::*> {
    using class_type = C;
    using ret_type = std::invoke_result_t<T C::*, C>; 
};

template <typename PMember, typename T = trait<PMember>>
using Index = std::map<typename T::ret_type, typename T::class_type>;

当然,这是C++17,因此您甚至可以跳过decltype:

template <auto PMember, typename T = trait<decltype(PMember)>>
using Index = std::map<typename T::ret_type, typename T::class_type>;

Index<&Foo::x>        indexOnX;       // std::map<int, Foo>
Index<&Foo::get_name> indexOnGetName; // std::map<char*, Foo>
模板
使用Index=std::map;
指数indexOnX;//标准::地图
索引indexOnGetName;//标准::地图

是的,我需要使用ret类型的std::conditional\t版本。我假设所有的艰苦工作都发生在std::invoke_result_t中,因为代码也与const成员函数一起工作。最后,绕过decltype正是我想要做的,因为我现在想编写从Foo中提取密钥的方法。对于模板元编程的初学者,我不知道的模式是声明一个模板化的trait类,然后为指向成员的指针定义trait的专门化,在成员类型和类类型上模板化。在实例化索引别名模板时,C++17为trait模板找到一个匹配项,该模板将指向成员的指针扩展为其各个部分。
template <class >
struct trait;

template <class C, class T>
struct trait<T C::*> {
    using class_type = C;
    using ret_type = std::invoke_result_t<T C::*, C>; 
};

template <typename PMember, typename T = trait<PMember>>
using Index = std::map<typename T::ret_type, typename T::class_type>;
using ret_type = std::conditional_t<
    std::is_function_v<T>,
    std::invoke_result_t<T C::*, C>,
    T>;
template <auto PMember, typename T = trait<decltype(PMember)>>
using Index = std::map<typename T::ret_type, typename T::class_type>;

Index<&Foo::x>        indexOnX;       // std::map<int, Foo>
Index<&Foo::get_name> indexOnGetName; // std::map<char*, Foo>