从类模板派生的类的公共函数
我有一个具有以下类层次结构的程序:
struct TYPE_ONE { int i; };
struct TYPE_TWO { int i; };
template<typename T>
class Base
{
public:
int fun(int i);
};
template<typename T>
int Base<T>::fun(int i)
{
return 42 * i;
}
class A : public Base<TYPE_ONE>
{
public:
void another_fun()
{
fun(1);
}
} a;
class B : public Base<TYPE_TWO>
{
public:
void another_fun()
{
fun(2);
}
} b;
int main()
{
a.another_fun();
b.another_fun();
}
如您所见,fun
不依赖于类型。不幸的是,编译器正在生成两个有趣的方法。每种类型一个。
$ nm --demangle ./a.out | grep fun
0000000000001150 W A::another_fun()
0000000000001174 W B::another_fun()
0000000000001198 W Base<TYPE_ONE>::fun(int)
00000000000011b0 W Base<TYPE_TWO>::fun(int)
有没有一种方法可以强制编译器为这两个类仅生成一个公共函数?
我发现我可以尝试通过将 fun
设为静态并向模板添加默认参数来解决此问题。类似于:
template<typename T=TYPE_ONE>
class Base
{
public:
static int fun(int i);
};
class A : public Base<TYPE_ONE>
{
public:
void another_fun()
{
Base<>::fun(1);
}
} a;
class B : public Base<TYPE_TWO>
{
public:
void another_fun()
{
Base<>::fun(2);
}
} b;
使用此编译器仅生成一个 fun
方法:
$ nm --demangle ./a.out | grep fun
0000000000001150 W A::another_fun()
000000000000116e W B::another_fun()
000000000000118c W Base<TYPE_ONE>::fun(int)
但是对于这个问题有更干净的解决方案吗?
I have a program with the following class hierarchy:
struct TYPE_ONE { int i; };
struct TYPE_TWO { int i; };
template<typename T>
class Base
{
public:
int fun(int i);
};
template<typename T>
int Base<T>::fun(int i)
{
return 42 * i;
}
class A : public Base<TYPE_ONE>
{
public:
void another_fun()
{
fun(1);
}
} a;
class B : public Base<TYPE_TWO>
{
public:
void another_fun()
{
fun(2);
}
} b;
int main()
{
a.another_fun();
b.another_fun();
}
As you can see the fun
doesn't depend on the type. Unfortunately compiler is generating two fun
methods. One for each type.
$ nm --demangle ./a.out | grep fun
0000000000001150 W A::another_fun()
0000000000001174 W B::another_fun()
0000000000001198 W Base<TYPE_ONE>::fun(int)
00000000000011b0 W Base<TYPE_TWO>::fun(int)
Is there a way to force compiler to generate only one common function for both classes?
I see that I could try to workaround this by making fun
static and adding default argument to the template. Something like:
template<typename T=TYPE_ONE>
class Base
{
public:
static int fun(int i);
};
class A : public Base<TYPE_ONE>
{
public:
void another_fun()
{
Base<>::fun(1);
}
} a;
class B : public Base<TYPE_TWO>
{
public:
void another_fun()
{
Base<>::fun(2);
}
} b;
With this compiler generates only one fun
method:
$ nm --demangle ./a.out | grep fun
0000000000001150 W A::another_fun()
000000000000116e W B::another_fun()
000000000000118c W Base<TYPE_ONE>::fun(int)
But is there a cleaner solution for this issue?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
下面定义了两种不同的类型,它们恰好具有完全相同的实现:
这会误导人们认为
fun()
应该共享相同的代码。但实际上,这是一个非常特殊的情况。由于这两种类型可以共享具有不同内存布局的符号
i
,因此需要不同的机器代码来执行表面上相同的 i*42。您甚至可能会遇到不同类型的情况,同样,机器代码将完全不同并且无法共享:
当然,编译器可以识别这些类型具有相同的布局并努力使用一些通用代码。但这根本不是义务。
如果模板类中有固定类型的公共部分,则应该将该公共部分重构为模板类的非模板基类。例如:
并相应地调整A和B。这里有一个 RealBase,无论您在其上构建什么模板。并且您的编译器自然只有一种 RealBase 实现。
The following defines two distinct types, that happen to have exactly the same implementation:
This misleads to think that
fun()
should share the same code.But in reality, this is a very exceptional circumstance. Because the two types could share a symbol
i
with a different memory layout, that would require a different machine code to perform the apparently identical i*42.You could even have the case of different types, where again, the machine code would be completely different and could not be shared:
Of course, the compiler could recognize that the types have an identical layout and make the effort of using some common code. But it's not at all an obligation.
If there is a common part in the template class with fixed types, you should refactor that common part into a non-template base to the template class. For example:
and adapt A and B accordingly. Here there is one RealBase, whatever template you build upon it. And your compiler would naturally have only one RealBase implementation.