c ++模板类打印功能

时间:2017-11-28 08:21:14

标签: c++ variadic-templates template-meta-programming

我正在尝试为我的模板类编写一个print函数:

struct ColumnKey;

template <class Type, class Key = ColumnKey>
class Column {
protected:
  std::shared_ptr<Type> doGet() {
    std::lock_guard<std::mutex> lock(mutex_);
    return std::make_shared<Type>(value_);
  }
  void doSet(const std::shared_ptr<Type> &value) {
    std::lock_guard<std::mutex> lock(mutex_);
    value_ = *value;
  }
private:
  Type value_;
  std::mutex mutex_;
};

template<class... Columns>
class Table : private Columns... {
public:
  template<class Type, class Key = ColumnKey>
  std::shared_ptr<Type> get() {
    return Column<Type, Key>::doGet();
  }

  template<class Type, class Key = ColumnKey>
  void set(const std::shared_ptr<Type> &value) {
    Column<Type, Key>::doSet(value);
  }

  std::string get_table_row() {
    return "hello_row";
  }
};

我想在课程get_table_row中创建一个函数Table,该函数返回columnA + "," + columnB + "," + ..

我试图以这种方式编写,但遇到编译错误。有人能指出我的方法中的错误吗?

    template <class Column<class Type, class Key = ColumnKey>>
    std::string get_row() {
        return std::to_string( *Column<Type, Key>::doGet() );
    }

    template <class Column<class Type, class Key = ColumnKey>, class... Columns>
    std::string get_row() {
        return ( std::to_string(*Column<Type, Key>::doGet()) + "," + Columns.get_row() );
    }

我正在努力做到这一点,任何人都可以指导我吗?

3 个答案:

答案 0 :(得分:0)

这是一个可行的解决方案。

struct printer遍历可变参数模板并为每种类型调用Table :: get:

template <typename TableT>
struct printer
{
  printer(TableT& t): m_table(t) {}

  template <typename T>
  void impl(std::ostream& output)
  {
    using type = typename column_type<T>::type;
    output << *m_table.template get<type>();
  }

  template <typename First, typename Second, typename... Other>
  void impl(std::ostream& output)
  {
    impl<First>(output);
    impl<Second, Other...>(output);
  }

  template <typename... T>
  std::string invoke()
  {
    std::ostringstream out;
    impl<T...>(out);
    return out.str();
  }

  TableT& m_table;
};

我写了一个特性来推断专栏Type

template <typename> struct column_type;
template <template <typename, typename> class Column, typename Type, typename Key>
struct column_type<Column<Type, Key>>
{
    using type = Type;
};

为了使用打印机,我将列类型保存在元组中并将其解压缩:

template <typename... Columns>
class Table: private Columns...
{
  using columns_t = std::tuple<Columns...>;
public:
    std::string get_table_row() {
    return unpack<columns_t>::invoke(*this);
  }
};

struct unpack调用打印机:

template <typename> struct unpack;
template <typename... T> struct unpack<std::tuple<T...>>
{
  template <typename TableT>
  static std::string invoke(TableT& t)
  {
    printer<TableT> p(t);
    return p.invoke<T...>();
  }
};

答案 1 :(得分:0)

您的get_row会员功能确实不正确。我们需要递归处理列。为此,我们需要一个辅助类(因为函数模板不能部分专门化),以及辅助类型特征来推导出Column的{​​{1}}和Key参数:

Type

现在,在template <typename> struct column_traits; template <typename Type, typename Key> struct column_traits<Column<Type, Key>> { using type = Type; using key = Key; }; template <typename...> struct TableRowPrinter; template <typename Col> struct TableRowPrinter<Col> { template <typename TableT> static std::string get_row(TableT& table) { using col_traits = column_traits<Col>; return std::to_string( *table.template get<typename col_traits::type, typename col_traits::key>()); } }; template <typename HeadCol, typename... Cols> struct TableRowPrinter<HeadCol, Cols...> { template <typename TableT> static std::string get_row(TableT& table) { using col_traits = column_traits<HeadCol>; return std::to_string( *table.template get<typename col_traits::type, typename col_traits::key>()) + ", " + TableRowPrinter<Cols...>::get_row(table); } }; 类模板中,您需要做的就是添加正确的成员函数:

Table

您可以在Coliru上看到一个有效的例子。

注意:我没有&#34;清洁&#34;不寻常的std::string get_row() { return TableRowPrinter<Columns...>::get_row(*this); } 用法......这是另一个话题......

答案 2 :(得分:0)

您应该使用fold expressions

template<typename T, typename K>
struct Column
{
    T val;
};

template<typename FirstColumn, typename... Columns>
struct Table : private FirstColumn, private Columns...
{
    std::string get_table_row()
    {
        using std::to_string;
        return (to_string(FirstColumn::val) + ... + ("," + to_string(Columns::val)));
    }
};

如果你有一个用例,你可以专注于零列的情况。