【发布时间】:2021-02-20 07:27:59
【问题描述】:
我正在尝试通过模板减少代码重复。我已经将大部分代码移到了这个帮助器iterate_function_from_CSC_helper,它现在是一个模板。然而,这个函数仍然重复了很多代码,只是为了调用模板的不同特化:
std::function<std::pair<int, double>(int idx)>
IterateFunctionFromCSC(const void* col_ptr, int col_ptr_type, const int32_t* indices, const void* data, int data_type, int64_t ncol_ptr, int64_t , int col_idx) {
CHECK(col_idx < ncol_ptr && col_idx >= 0);
if (data_type == C_API_DTYPE_FLOAT32) {
if (col_ptr_type == C_API_DTYPE_INT32) {
return iterate_function_from_CSC_helper<float, int32_t>(col_ptr, indices, data, col_idx);
} else if (col_ptr_type == C_API_DTYPE_INT64) {
return iterate_function_from_CSC_helper<float, int64_t>(col_ptr, indices, data, col_idx);
}
} else if (data_type == C_API_DTYPE_FLOAT64) {
if (col_ptr_type == C_API_DTYPE_INT32) {
return iterate_function_from_CSC_helper<double, int32_t>(col_ptr, indices, data, col_idx);
} else if (col_ptr_type == C_API_DTYPE_INT64) {
return iterate_function_from_CSC_helper<double, int64_t>(col_ptr, indices, data, col_idx);
}
}
Log::Fatal("Unknown data type in CSC matrix");
return nullptr;
}
我想自动将运行时收到的整数 data_type 和 col_ptr_dtype 分别映射到 float/double 和 int32_t/int64_t 类型,并用它们调用模板。像这样的:
std::function<std::pair<int, double>(int idx)>
IterateFunctionFromCSC(const void* col_ptr, int col_ptr_type, const int32_t* indices, const void* data, int data_type, int64_t ncol_ptr, int64_t , int col_idx) {
CHECK(col_idx < ncol_ptr && col_idx >= 0);
if (<TTag<data_col>::invalid_type || TTag<col_ptr_type>::invalid_type) {
Log::Fatal("Unknown data type in CSC matrix");
return nullptr;
}
return iterate_function_from_CSC_helper<TTag<data_type>::type, TTag<col_ptr_type>::type>(col_ptr, indices, data, col_idx);
}
这可能吗?我认为通过一些元编程可以消除这种情况。
我尝试了以下方法,但无法使 dummy_IterateFunctionFromCSC 使用非 const 输入(运行时会出现这种情况):
#include <cstdint>
#include <stdio.h>
#include <iostream>
#include <type_traits>
#define C_API_DTYPE_FLOAT32 (0) /*!< \brief float32 (single precision float). */
#define C_API_DTYPE_FLOAT64 (1) /*!< \brief float64 (double precision float). */
#define C_API_DTYPE_INT32 (2) /*!< \brief int32. */
#define C_API_DTYPE_INT64 (3) /*!< \brief int64. */
struct TTagInvalidType {}; //! Meant for invalid types in TTag.
template <int C_API_DTYPE>
struct TTag {
using type = TTagInvalidType;
};
template<>
struct TTag<C_API_DTYPE_FLOAT32> {
using type = float;
};
template <>
struct TTag<C_API_DTYPE_FLOAT64> {
using type = double;
};
template <>
struct TTag<C_API_DTYPE_INT32> {
using type = int32_t;
};
template <>
struct TTag<C_API_DTYPE_INT64> {
using type = int64_t;
};
template <typename T>
void example_f () {
T x = 3.6;
std::cout << x << "\n";
}
template <>
void example_f<TTagInvalidType>() {
std::cout << "Abort!\n";
}
template<int x>
void dummy_IterateFunctionFromCSC() {
f<typename TTag<x>::type>();
}
int main() {
const int m = 2; // Doesn't work for non const integers (true at runtime)
dummy_IterateFunctionFromCSC<m>();
}
这可以编译,但只能使用常量 m,而不是使用从用户那里收到的整数。
这是不可能的,因为类型分派必须在编译时计算吗?或者有可能以及如何? :D
谢谢你:)
【问题讨论】:
-
您想要根据运行时值的模板实例化吗?我理解正确吗?如果是这样,你不能。
-
我们的模板函数 (4) 中有一组有限且非常小的类型:int、float、long、double。我希望在运行时将 2 个整数转换为 2 种类型,以专门化我的模板函数调用
iterate_function_from_CSC_helper<type1, type2>(args...),因为我们在 API 中为用户公开IterateFunctionFromCSC(这是我们的入口点)。这就是模板实例化的意思?那是不可能的? -
非类型参数,如
dummy_IterateFunctionFromCSC<m>()中的m需要为constexpr,所以if(m == 2) dummy_IterateFunctionFromCSC<2>();可以工作。
标签: c++ c++11 template-meta-programming