This question continues Non-static data members class deduction
Here are the unnamed argument functions, that I'm using to return std::string
representation of the data type
struct Boo {};
struct Foo {};
std::string class2str(const double) { return "Floating"; };
std::string class2str(const int) { return "Fixed Point"; };
std::string class2str(const Foo) { return "Class Foo"; };
std::string class2str(const Boo) { return "Class Boo"; };
int main(int argc, char* argv[])
{
int x_a;
double x_b;
Foo F;
Boo B;
std::cout << "x_a :" << class2str(x_a) << std::endl;
std::cout << "x_b :" << class2str(x_b) << std::endl;
std::cout << "Foo :" << class2str(F) << std::endl;
std::cout << "Boo :" << class2str(B) << std::endl;
};
For type deduction from the non-static member, I am using template:
struct Foo { double A = 33; }
template<typename Class, typename MemType>
std::string class2str(MemType Class::* mData)
{
return class2str(MemType{}); // Use of empty constructor
}
std::cout << "Foo::A :" << class2str(&Foo::A) << std::endl;
But this template requires the creation of an object with an empty constructor, which may simply not be there
struct Boo
{
double A;
Boo() = delete;
Boo(int x) :A(x) {};
};
struct Foo
{
double A = 33;
Boo b{ 0 };
};
// Compilation error: use of deleted function ‘Boo::Boo()’
std::cout << "Boo::b :" << class2str(&Foo::b) << std::endl;
How to implement this functionality, but without calling an empty constructor?
See online demo: https://onlinegdb.com/lpc5o8pUKy
(As I started writing the answer there was no answer to the question, but as I was about to post it I saw @Jarod42's answer which already show the tag dispatch approach. Posting this answer nonetheless as it uses a slightly different approach of full specializations of a deleted primary template, instead of non-template overloads)
You can use tag dispatch to delegate calls:
#include <iostream>
struct Boo {
double A;
Boo() = delete;
Boo(int x) : A(x){};
};
struct Foo {
double A = 33;
Boo b{0};
};
namespace detail {
template <typename T> struct Tag {};
template <typename T> std::string class2str_impl(Tag<T>) = delete;
template <> std::string class2str_impl(Tag<double>) { return "Floating"; };
template <> std::string class2str_impl(Tag<int>) { return "Fixed Point"; };
template <> std::string class2str_impl(Tag<Foo>) { return "Class Foo"; };
template <> std::string class2str_impl(Tag<Boo>) { return "Class Boo"; };
} // namespace detail
template <typename T> std::string class2str(T) {
return class2str_impl(detail::Tag<T>{});
}
template <typename Class, typename MemType>
std::string class2str(MemType Class::*) {
return class2str_impl(detail::Tag<MemType>{});
}
int main() {
int x_a{42};
double x_b{4.2};
Foo F{};
Boo B{x_a};
std::cout << "x_a :" << class2str(x_a) << std::endl;
std::cout << "x_b :" << class2str(x_b) << std::endl;
std::cout << "Foo :" << class2str(F) << std::endl;
std::cout << "Boo :" << class2str(B) << std::endl;
std::cout << "Boo::b :" << class2str(&Foo::b) << std::endl;
};
where the primary template of class2str_impl
may either be deleted (as above), or implement a custom message that a given type does not have a mapped string.
All your overloads currently take object. You might take type instead, or object which hold type:
template <typename T> struct Tag{};
std::string class2str(Tag<double>){ return "Floating";};
std::string class2str(Tag<int>){ return "Fixed Point";};
std::string class2str(Tag<Foo>){ return "Class Foo";};
std::string class2str(Tag<Boo>){ return "Class Boo";};
template<typename Class, typename MemType>
std::string class2str(Tag<MemType Class::*>)
{
return class2str(Tag<MemType> {});
}
With usage:
int main(int argc, char *argv[]) {
int x_a;
double x_b;
Foo F;
Boo B;
std::cout<< "x_a :" << class2str(Tag<decltype(x_a)>{}) <<std::endl;
std::cout<< "x_b :" << class2str(Tag<decltype(x_b)>{}) <<std::endl;
std::cout<< "Foo :" << class2str(Tag<decltype(F)>{}) <<std::endl;
std::cout<< "Boo :" << class2str(Tag<decltype(B)>{}) <<std::endl;
// or
std::cout<< "int :" << class2str(Tag<int>{}) <<std::endl;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With