我正在尝试为我的模板类编写一个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() );
}
我正在努力做到这一点,任何人都可以指导我吗?
答案 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)));
}
};
如果你有一个用例,你可以专注于零列的情况。