【发布时间】:2014-01-03 01:48:59
【问题描述】:
大家好(新年快乐!)
我正在用 C++ 编写一个(不是真的)简单项目(我的第一个项目,来自纯 C)。我想知道是否有一种方法可以简化具有相同模板模式的多个函数的定义。我认为一个例子会更好地解释这个问题。
上下文
假设我有一个代表数字列表的“Set”类,定义为
template <class T>
class Set {
static_assert(std::is_arithmetic<T>(), "Template argument must be an arithmetic type.");
T *_address;
...
}
所以如果我有一个实例(比如Set<double>)和一个数组U array[N],其中U 是另一种算术类型,N 是一个整数,我希望能够执行一些操作,例如将数组的值分配给Set 的值。因此我在类中创建了函数模板
template <class U, int N>
void assign(U (&s)[N]) {
static_assert(std::is_arithmetic<U>(), "Template argument must be an arithmetic type.");
errlog(E_BAD_ARRAY_SIZE, N == _size);
idx_t i = 0;
do {
_address[i] = value[i];
} while (++i < size);
}
问题
就我的测试而言,上面的代码运行良好。但是我发现它真的很难看,因为我需要static_assert 来确保只将算术类型作为参数(参数U)并且我需要一种方法来确定数组大小(参数N) .另外,我还没有完成assign 函数,但我需要很多其他函数,例如add、multiply、scalar_product 等等!
第一种解决方案
那时我想知道是否有更漂亮的方法来编写这种类。经过一些工作,我想出了一个预处理器指令:
#define arithmetic_v(_U_, _N_, _DECL_, ...) \
template <class U, idx_t N> _DECL_ \
{ \
static_assert(std::is_arithmetic<U>(),"Rvalue is not an arithmetic type."); \
errlog(E_BAD_ARRAY_SIZE, N == _size); \
__VA_ARGS__ \
}
因此将我的函数定义为
arithmetic_v(U, N,
void assign(U (&value)[N]),
idx_t i = 0;
do {
_address[i] = value[i];
} while (++i < _size);
)
这在某种程度上更干净,但仍然不是最好的,因为我不得不丢失包裹函数主体的括号(必须在函数本身中包含 static_assert 以使模板参数 U 在范围内)。
问题
我发现的解决方案似乎工作得很好,代码比以前更具可读性,但是......我不能使用另一个构造来构建所有函数的更清晰的定义并且仍然保留static_assert 和有关数组大小的信息?为我需要的每个功能重复一次模板代码真的很难看...
谢谢
我只是想了解该语言,因此任何有关此论点的其他信息将不胜感激。我已经尽可能多地搜索,但找不到任何东西(也许我只是想不出合适的关键字来询问谷歌以找到相关的东西)。提前感谢您的帮助,祝大家新年快乐!
詹卢卡
【问题讨论】:
-
这个问题更适合CodeReview。
-
#definebig no no :Espan> -
为什么要在运行时测试大小?为什么你需要测试
U? -
为什么要定义自己的?使用
std::set。 -
@Yakk 的大小并不总是在运行时进行测试(只有在编译时定义了某些单词)。 errlog 是一个预处理器宏,在这种情况下包含一种
static_assert,但在某些情况下,作为参数传递的数组只能在运行时构建。我需要测试U,因为在双精度和字符串之间求和并不是我的想法。我根本不想创建字符串集!如果您知道任何更好的方法来测试模板参数是否属于算术类型,我会很乐意倾听。
标签: c++ templates preprocessor-directive