一些關于模板/元編程技術的改進問題。
下面的代碼的動機是方便地從一個具有c風格的API的sql db驅動中提取正確型別的資料。結果集的行被逐一回傳為char**。我在下面用一些陣列字樣來模擬這個情況。
我將這個char**行資料包裹在一個類中以提供型別提取。此外,還有一個模板化的single_column()函式,它可以在呼叫者選擇的容器中回傳一個單一型別的列。
代碼的作業原理如圖所示。問題是:
- 用一個
static_cast<void>封鎖非專用版本的row::get<ValueType>似乎是一個黑客。有更好的方法嗎?我不認為答案是簡單地寫get_int(),get_long()等,因為我們希望像single_column()這樣的通用代碼,只是選擇指定的getter。 - 用
if constexpr檢測push_back()是否存在的型別特征 "方法存在調度 "作業正常。是否有更優雅的方法使用C 17?即沒有C 20的概念?
多謝
#include <cstddef>/span>
#include <iostream>
#include <string>
#include <unordered_set>/span>
#include <vector>
//有沒有更直接的方法(不使用c 20的概念)。
template <typename C, typename = void>
struct has_push_back : std::false_type {};
template <typename C>
struct has_push_back<
C, std::void_t<decltype(std::declval<C>()。 push_back(std::declval<typename C::value_type>())>>。
: std::true_type {};
class row {
public:
explicit row(const char** row) : row_(row) {}。
template <typename ValueType>
ValueType get(unsigned idx) const{
//應該總是失敗的!用戶必須呼叫一個現有的專業!。
//有一個 "更好 "的方法嗎?
return static_cast<void>(row_[idx]); // NOLINT ptr arith
}
template<>
[[nodiscard]] int get<int> (unsigned idx) const {
return std::stoi(row_[idx]); // NOLINT ptr arith
}
template <>
[[nodiscard]] long get<long> (unsigned idx) const {
return std::stol(row_[idx]); // NOLINT ptr arith
}
template <>
[[nodiscard]] std::string get<std::string> (unsigned idx) const{
return row_[idx]; // NOLINT ptr arith {
}
template <>
[[nodiscard]] const char* get< const char*>(unsigned idx) const {
return row_[idx]; // NOLINT ptr arith {
}
private:
const char** row_;
};
template <typename ContainerType>
ContainerType single_column(const std: :vector<row>& rows, unsigned col = 0){
容器型別值。
using ValueType = typename ContainerType::value_type;
for (auto&& row: rows) {
if constexpr (has_push_back<ContainerType>:value) /span>這是 "最好 "的方法嗎?
values.push_back(row.get<ValueType>(col))。
else[/span
values.insert(row.get<ValueType>(col) )。
}
return values;
}
int main() {
//以c-arrays的方式處理,因為它是來自db驅動的方式。
//代表從資料庫回來的原始資料。
///NOLINTNEXTLINE C-arrays。
const char* data[] [3] = {
{
"1-some text"。
"122222222",
"1333333333333333",
},
{
"2-some text",
"222222222",
"2333333333333333",
},
{
"2-some text", //dupe value。
"322222222",
"3333333333333333",
},
};
std::vector<row> rows; // simulationg rows being returned the db server。
for (auto& r: data) rows.emplace_back(r)。
// now retrieve column-wise as correct types into vectors.
for (auto&& e: single_column< std::vector< std: :string>>(rows, 0)) std::cout << e << ", ";
std::cout << std::endl;
for (auto&& e: single_column< std:: vector<int>>(rows, 1)) std::cout << e << " ,"。
std::cout << std::endl;
for (auto&& e: single_column< std:: vector<long>>(rows, 2)) std::cout << e << ", "。
std::cout << std::endl;
//現在進入unordered_sets。
for (auto&& e: single_column< std::unordered_set< std: :string>>(rows, 0)) std::cout << e << ", ";
std::cout << std::endl;
for (auto&& e: single_column< std:: unordered_set<int>>(rows, 1)) std::cout << e << " ,"。
std::cout << std::endl;
for (auto&& e: single_column< std:: unordered_set<long>>(rows, 2)) std::cout << e << " ,"。
std::cout << std::endl;
//compile error - the static_cast<void> fails: works, but is there a "better" way.
// double d = rows[0].get<double>(1);
}
uj5u.com熱心網友回復:
用static_cast封鎖row::get的非專用版本似乎是一個黑客。是否有更好的方法。我不認為答案是簡單地撰寫get_int()、get_long()等,因為我們希望像single_column()這樣的通用代碼能夠直接選擇指定的getter.
。
你可以洗掉它:
template <typename ValueType>
ValueType get(unsignedidx) const = delete。
用
if constexpr檢測push_back()是否存在的型別特征 "方法存在調度 "作業正常。是否有一個更優雅的方法使用C 17?即沒有C 20的概念?
你的方法很好(包括創建和使用tyetrait);
C 20的概念允許使用requires的更好的語法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/329617.html
標籤:
下一篇:在C 向量中高效交換元素
