【发布时间】:2016-04-07 20:22:18
【问题描述】:
还有......我不想使用函数指针,我真的想直接使用函数本身(因此可以内联或应用其他优化)。
假设:我有一个模板函数/类,它将计算一些数学内容,模板参数是整数类型,可能是 unsigned int32_t 或 unsigned int64_t。
在某些时候我需要随机数,所以我需要一个生成器,在一种情况下我将使用mt19937,在另一种情况下使用mt19937_64。所以实际的类型名称是不同的,但我必须选择一个并实际写在源代码中。
显然,整数类型的特征类可以正常工作(这就是我现在正在做的事情)。但在我看来,这种一次性使用在语法方面相当重量级,而且有点非本地(如果你明白我的意思,请阅读源代码)。
另一种方法是将生成器的使用封装在一些(通用)函数中,并为我的两个整数类型提供它的完全专业化。这其实没问题。
但是:还有其他选择吗?我可以在这里使用某种编译时“if”或“switch”(不完全是enable-if,它启用/禁用模板实例化)吗?或者别的什么(也许比我没看到的模板元编程更简单)?
(P.S. 请不要挂断mt19937 和mt19937_64 - 我知道它们都是我可以用我的整数类型实例化自己的类型的别名 - 但我更愿意使用标准定义他们的大量相当神奇的数字。另外,我不仅对mt19937/mt19937_64 感兴趣,还对其他类似案例感兴趣。)
这是我的特征类的代码目前的样子:
template <class Base>
struct traits { };
template <>
struct traits<unsigned __int32>
{
using base_t = unsigned __int32;
static const int nbits = std::numeric_limits<base_t>::digits;
using random_engine_t = std::mt19937;
...
};
template <>
struct traits<unsigned __int64>
{
using base_t = unsigned __int64;
static const int nbits = std::numeric_limits<base_t>::digits;
using random_engine_t = std::mt19937_64;
...
};
【问题讨论】:
-
请发布您用于特征的代码。
-
特征有什么问题?是不是你只需要
traits<T>::random_engine_t在一个地方,所以你不喜欢样板? -
差不多,而且样板远离使用点。这意味着您必须为抽象发明一个名称并记住它,而不是仅在您想要使用它们的地方直接/就地使用两个原始名称。 (当然,围绕着一些额外的语法,希望对于“合理”的某些 C++ 相对值来说“相当容易阅读”。)
-
您可能会无缘无故地担心函数指针。如果
foo(void(*))是inline,调用foo(&bar)将允许优化器内联foo,发现对于那个特定内联实例调用的函数总是bar,然后继续内联。 -
@MSalters - 很好的提示 - 我会在生成的程序集中检查一下,谢谢。
标签: c++ templates c++11 template-meta-programming