c++ - 模板参数作为函数未命名参数

标签 c++ class templates c++17 function-templates

这个问题继续Non-static data members class deduction
这是未命名的参数函数,我用它来返回 std::string数据类型的表示

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;
};
对于非静态成员的类型推导,我使用模板:
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;
但是这个模板需要创建一个带有空构造函数的对象,它可能根本不存在
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;
如何实现此功能,但不调用空构造函数?
看在线演示:https://onlinegdb.com/lpc5o8pUKy

最佳答案

(当我开始写答案时,这个问题没有答案,但是当我准备发布它时,我看到 @Jarod42 的答案已经显示了标签调度方法。尽管如此,发布这个答案,因为它使用了一种稍微不同的完全特化的方法删除的主模板,而不是非模板重载)

您可以使用标签调度来委托(delegate)调用:

#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;
};
其中class2str_impl的主模板可以被删除(如上所述),或者实现给定类型没有映射字符串的自定义消息。

关于c++ - 模板参数作为函数未命名参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68815240/

相关文章:

c++ - 将批处理文件编译成EXE文件

c++ - 自动向下转换指向派生对象的指针

c++ - C++ 模板中具有参数化类型的结构如何初始化?

Ruby 模块可以访问它所需要的类方法吗?

c++ - 如何判断参数何时来自硬编码数字?

c++ - 为什么不需要手动释放 vector ?

c++ - 未找到 libstdc++-6.dll

C++ 根据数学方程生成随机数。

c++ - 如何在 C++ 中定义字符串常量?

c# - 静态类和变量