Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++_Templates_C++11_Pointer To Member - Fatal编程技术网

C++ 模板成员函数专用于指向数据成员的指针

C++ 模板成员函数专用于指向数据成员的指针,c++,templates,c++11,pointer-to-member,C++,Templates,C++11,Pointer To Member,我想定义一个空的静态模板成员函数,该函数(显式地)在指向数据成员的指针上专门化,并且对于每个专门化,可以有不同的返回类型 它应该返回关于每个属性的一些详细信息,因此我将调用此方法trait。返回的trait对象类型将由其他模板检查,因此整个机制必须在编译时可用 到目前为止,我有这样的东西(当然是坏代码): class-Foo{ //一些数据成员 int a;std::string b;int c; //如何在这里声明通用模板? //如果下面的任何专门化都不匹配,则编译时错误应随之发生 //a的专

我想定义一个空的静态模板成员函数,该函数(显式地)在指向数据成员的指针上专门化,并且对于每个专门化,可以有不同的返回类型

它应该返回关于每个属性的一些详细信息,因此我将调用此方法
trait
。返回的trait对象类型将由其他模板检查,因此整个机制必须在编译时可用

到目前为止,我有这样的东西(当然是坏代码):

class-Foo{
//一些数据成员
int a;std::string b;int c;
//如何在这里声明通用模板?
//如果下面的任何专门化都不匹配,则编译时错误应随之发生
//a的专门化(aTraitExpr是从宏扩展的,所以可以重复)
模板自动特征()->decltype(aTraitExpr){return aTraitExpr;}
//b的专门化;返回类型将不同于trait
模板自动特征()->decltype(bTraitExpr){return bTraitExpr;}
};
//一些在编译时查询特征的代码
//例如,假设所有可能的特征类型都声明可序列化
//这对a是正确的,对b是错误的
Foo*Foo;
模板空洞剂量序列化(…);
模板无效的doSerialization(…){…};
模板void doSerialization(…){/*no op*/};
剂量系列化(…);//->doSerialization(foo)
剂量系列化(…);//->剂量系列化(…)
剂量系列化(…);//->编译错误,未定义专门化Foo::trait
你能得到一些关于如何做到这一点的提示吗?(我并不是要发明一个新的序列化系统,我已经使用了boost::serialization;每个特性中都会有更多的信息,这只是一个示例,说明为什么在编译时需要它)


编辑:我能够得到接近我想要的东西,如图所示。我放弃了使用
trait()
(现在),因此有一个静态函数
getTrait_a()
,它返回对可修改类型trait的引用,但在编译时这些类型trait部分是固定的(例如,
Foo::TraitType_a::flags
)。感谢所有回答的人,不幸的是,我只能选择其中一个答案作为“答案”。

定义traits类的常用方法是围绕编译时常量表达式包装结构/类(而不是包装返回此类表达式的函数)。获取类成员函数的语法如下所示:

template
<
    SomeReturnType (SomeClass::*SomeMemberFunction)(SomeParameters)
>
class SomeTrait
{
    static const value = SomeCompileTimeConstantExpression;
};
doSerialization<&Foo::a>(...);
doSerialization<&Foo::b>(...);
doSerialization<&Foo::c>(...);
此外,重载函数模板比专门化函数模板更为惯用:

template<int V> struct Int2Type { enum { value = V }; };

Foo* foo;

template
<
    void (Foo::*f)()
>
void doSerialization(...)
{
    dispatch::doSerialization(Int2Type< trait<f>::value >(), ...);
}

namespace dispatch {

doSerialization(Int2Type< true >, ...) { ... };

doSerialization(Int2Type< false >, ...) { /* no-op */ };

} // namespace dispatch
template struct Int2Type{enum{value=V};};
Foo*Foo;
模板
<
无效(Foo::*f)()
>
空穴剂量系列化(…)
{
dispatch::doSerialization(Int2Type(),…);
}
命名空间分派{
doSerialization(Int2Type,…){…};
doSerialization(Int2Type,…){/*no op*/};
}//命名空间分派
你可以这样称呼它:

template
<
    SomeReturnType (SomeClass::*SomeMemberFunction)(SomeParameters)
>
class SomeTrait
{
    static const value = SomeCompileTimeConstantExpression;
};
doSerialization<&Foo::a>(...);
doSerialization<&Foo::b>(...);
doSerialization<&Foo::c>(...);
doSerialization(…);
剂量系列化(…);
剂量系列化(…);

看起来您需要几个重载而不是专门化。不幸的是,您没有详细说明什么是
xTraitExpr
,但它似乎只是一个定义了成员
isSerializable
的类型。我可能会这样去

class Foo {
   // your members have been omitted to save space...

   template<typename T, T Foo::*M>
   struct W { };

   static decltype(aTraitExpr) trait(W<int, &Foo::a>) {
     return aTraitExpr;
   }

   static decltype(bTraitExpr) trait(W<std::string, &Foo::b>) {
     return bTraitExpr;
   }

   // other overloads for other members...

public:
   // overloads for each member type
   template<int Foo::*M> 
   static decltype(trait(W<int, M>())) trait() { 
     return trait(W<int, M>()); 
   }

   template<std::string Foo::*M> 
   static decltype(trait(W<std::string, M>())) trait()  { 
     return trait(W<std::string, M>()); 
   }
};

我认为在这里使用函数模板是没有意义的。也就是说,使用类模板代替它也不是那么方便:您必须考虑这样一个事实,即非静态数据成员可以有不同的类型,并且可以有多个具有相同类型的非静态数据成员。有一种可能性:

template<typename T>
struct is_serializable: std::false_type {};

struct Foo {
    int a; std::string b; int c;

    // Primary template left undefined on purpose
    // alternatively, could use a static_assert on a dependent
    // std::false_type::value for better diagnostics
    template<typename T, T t>
    struct attribute_trait;
};

// Define explicit specializations outside of class
template<>
struct Foo::attribute_trait<int Foo::*, &Foo::a>
: is_serializable<int> {};

template<>
struct Foo::attribute_trait<std::string Foo::*, &Foo::b>
: is_serializable<std::string> {};
模板
结构是可序列化的:std::false_type{};
结构Foo{
int a;std::string b;int c;
//主模板故意未定义
//或者,可以对依赖项使用静态断言
//std::false_type::值用于更好的诊断
模板
结构特征;
};
//定义类外的显式专门化
模板
struct Foo::attribute\u trait
:是可序列化的{};
模板
struct Foo::attribute\u trait
:是可序列化的{};
它可用作

doSerialization<Foo::attribute_trait<decltype(&Foo::a), &Foo::a>::value>(/* stuff */);
doSerialization(/*stuff*/);

xTraitExpr
Trait().modifier1().modifier2()
,我需要从中提取编译时参数。很抱歉没有说清楚,我不想把问题复杂化太多。
template<typename T>
struct is_serializable: std::false_type {};

struct Foo {
    int a; std::string b; int c;

    // Primary template left undefined on purpose
    // alternatively, could use a static_assert on a dependent
    // std::false_type::value for better diagnostics
    template<typename T, T t>
    struct attribute_trait;
};

// Define explicit specializations outside of class
template<>
struct Foo::attribute_trait<int Foo::*, &Foo::a>
: is_serializable<int> {};

template<>
struct Foo::attribute_trait<std::string Foo::*, &Foo::b>
: is_serializable<std::string> {};
doSerialization<Foo::attribute_trait<decltype(&Foo::a), &Foo::a>::value>(/* stuff */);