【发布时间】:2012-01-22 09:24:29
【问题描述】:
考虑以下代码:
main.cpp:
#include <iostream>
typedef void ( * fncptr)(void);
extern void externalfunc(void);
template<void( * test)(void)>
class Bar
{
public:
Bar() { test(); }
};
void localfunc()
{
std::cout << "Hello World" << std::endl;
}
constexpr fncptr alias = localfunc;
extern fncptr externalAlias;
int main(int argc, char* argv[])
{
Bar<localfunc> b;
Bar<alias> b2; // This wouldn't compile if alias wasn't constexpr
Bar<externalfunc> b3;
// Bar<externalAlias> b4;
return 0;
}
和external.cpp:
#include <iostream>
typedef void ( * fncptr)(void);
void externalfunc()
{
std::cout << "Hello external world" << std::endl;
}
fncptr externalAlias = externalfunc;
现在的问题是我需要主函数中的第 4 行之类的东西才能工作。我从外部 C 库中获取这些函数声明,所以我无法触及它们。目前第 4 行无法编译。 gcc 4.6 说“它必须是具有外部链接的函数的地址”。事实上,如果你让alias 不是 constexpr,它也会这么说,所以实际含义(我认为)应该解释为:“我不知道 100% 确定你给我的函数地址是恒定的我需要实例化这个模板”。有什么办法可以解决这个问题,因为我不能在main.cpp 中将externalalias 声明为constexpr?
在您使用替代解决方案之前:我已经在尝试通过将函数指针传递给构造函数并将它们保存在本地来完成这项工作,但我仍然感兴趣是否可以让模板版本正常工作:)。
【问题讨论】:
-
编译器应该如何知道
externalAlias的值是什么,以便实例化模板? -
是的,它不知道
externalAlias的值,但它是一个变量,因此它在编译时知道该变量的位置,因此它可以在其上进行模板化。 (如另一个答案所示(即我的答案:-)))。 -
为什么要使用模板进行类专业化?这就是继承的目的。 (即 test() 应该只是 Bar 的纯虚拟方法)然后在派生类中实现 test 对应于 localfunc、alias、externfunc 等......或者更好的是,Bar 只是一个独立的类,并且在它的构造函数中传递了一个实例和“ITest”类。使用模板做一些棘手的事情只会导致其他人继承无法维护的代码。
-
@selbie:我不想做类专业化,那个例子只是最小化的代码来显示问题。实际的问题实际上是我有一种资源逻辑/处理,我需要包装 3-4 个 C 函数,但是对于每种资源都有不同的功能(只是名称不同,而不是语法)。目前我只是为每组这些函数复制粘贴一个类,只替换类名和调用的实际函数,听起来很像手动模板......
-
@KillianDS - 我也这么认为。尽管如此,听起来您正在使用模板做一些极端的事情,而具有虚拟方法和接口的策略模式可能会这样做。在我的产品团队中,非常不鼓励使用模板——而且有充分的理由——它们可能更难调试和维护。通常对(接口)继承的一些应用就足够了。对于没有真正回答您的问题,我深表歉意。但我只是想鼓励您摆脱模板,而转向更易于维护的东西。 en.wikipedia.org/wiki/Strategy_pattern
标签: c++