非静态数据成员class推导

Non-static data members class deduction

我正在尝试解决类型推导问题。

这是演示代码,使用函数重载来定义传递的变量是 int 还是 double


std::string tcast( const double &x){ return "Floating Point";};
std::string tcast( const int    &x){ return "Integer";};

int main(){
    double dA;
    int    iB;
    std::cout << "Access to variable type \n";
    std::cout << "dA : "<< tcast( dA )<< std::endl;
    std::cout << "iB : "<< tcast( iB )<< std::endl;
}
Access to variable type 
dA : Floating Point
iB : Integer

但此函数不适用于非静态 class 成员:

struct Foo{
    double dA;
    int    iB;
};

int main(){

    std::cout << "Member dA : "<< tprint( &Foo::dA )<< std::endl;
    std::cout << "Member iB : "<< tprint( &Foo::iB )<< std::endl;

}

GCC 编译错误:

main.cpp: In function ‘int main(int, char**)’:
main.cpp:111:44: error: no matching function for call to ‘tcast(double Foo::*)’
  111 |     std::cout << "dA : "<< tcast( &Foo::dA )<< std::endl;
      |                                            ^
main.cpp:96:13: note: candidate: ‘std::string tcast(const double&)’
   96 | std::string tcast( const double &x){ return "Floating Point";};
      |             ^~~~~
main.cpp:96:34: note:   no known conversion for argument 1 from ‘double Foo::*’ to ‘const double&’
   96 | std::string tcast( const double &x){ return "Floating Point";};
      |                    ~~~~~~~~~~~~~~^
main.cpp:97:13: note: candidate: ‘std::string tcast(const int&)’
   97 | std::string tcast( const int    &x){ return "Integer";};
      |             ^~~~~
main.cpp:97:34: note:   no known conversion for argument 1 from ‘double Foo::*’ to ‘const int&’
   97 | std::string tcast( const int    &x){ return "Integer";};
      |                    ~~~~~~~~~~~~~~^

但是下面的代码可以编译:

template <typename T>
std::string tprint( const T    &x){ return typeid(x).name();};
...
std::cout << "dA : "<< tprint( dA )<< std::endl;
std::cout << "iB : "<< tprint( iB )<< std::endl;
std::cout << "Member dA : "<< tprint( &Foo::dA )<< std::endl;
std::cout << "Member iB : "<< tprint( &Foo::iB )<< std::endl;

因此编译器可以看到 dA 的类型为 double 和 iB int

dA : d
iB : i
Member dA : M3Food  // ends in d
Member iB : M3Fooi  // ends in i

那么如何推导非静态数据成员的类型才是正确的呢?

我们可以在这里利用 template argument deduction。指向成员数据语法的指针是

DataType Class::*Pointer

推导出成员类型后,我们可以调用所需的重载。

template<typename Class, typename MemType>
std::string tcast(MemType Class::*mData){
    return tcast(MemType{});
}

Link to the code in godbolt

您可以添加额外的重载:

template <typename C>
std::string tprint(double C::*){ return "member Floating Point";};

template <typename C>
std::string tprint(int C::*){ return "member Integer";};

Demo