我如何在专用和非专业版的C ++类之间共享代码?
这是我试图完成的一个人为的例子:
#include <iostream>
using namespace std;
template <size_t n> struct Y {
int one() { return 1; }
int two();
};
template <> struct Y<1> {
int one() { return 11; }
int two();
};
template <size_t n> int Y<n>::two() { return one() * 2; }
int main() {
Y<1> X;
cout << X.one();
cout << X.two();
return 0;
}
这在链接时失败:
Undefined symbols for architecture x86_64:
"Y<1ul>::two()", referenced from:
_main in test-7c4ebe.o
但是,如果我将Y<1> X;
更改为Y<2> X;
,编译就会成功。
我的目标是将two()
的示例实现用于该类的专用和非专业版本。
我能够通过这样的继承来解决这个问题:
#include <iostream>
using namespace std;
struct mixin {
virtual int one() = 0;
int two() { return one() * 2; }
};
template <size_t n> struct Y : public mixin {
int one() { return 1; }
};
template <> struct Y<1> : public mixin {
int one() { return 11; }
};
int main() {
Y<1> X;
cout << X.one();
cout << X.two();
return 0;
}
但我认为每次调用Y<n>.two()
都会产生不必要的v表查找,对吗?
有没有办法在专用和非专用版本之间共享代码而不滥用继承并引发v-table查找调用?
答案 0 :(得分:2)
您根本不需要将one
方法添加到mixin
。只需让mixin
使用非虚拟two
方法与派生类Y
共享其实现并使用CRTP。
#include <iostream>
using namespace std;
template <class Derive>
struct mixin {
int two() { return ((Derive *)this)->one() * 2; }
};
template <size_t n> struct Y : public mixin <Y<n>> {
int one() { return 1; }
};
template <> struct Y<1> : public mixin <Y<1>> {
int one() { return 11; }
};
int main() {
Y<1> X;
cout << X.one();
cout << X.two();
return 0;
}
答案 1 :(得分:2)
您可以指定一种方法,而不是类专业化:
template <size_t n> struct Y {
int one() { return 1; }
int two() { return one() * 2; }
int theird(); // declare only for Y<N>
};
template <>
int Y<1>::one() { return 11; }
// only for Y<1>
template <>
int Y<1>::theird() { return one()*two();}
答案 2 :(得分:1)
您可以反过来代替CRTP:
#include <iostream>
using namespace std;
template <size_t n> struct Y {
int one() { return 1; }
};
template <> struct Y<1> {
int one() { return 11; }
};
template <size_t n>
struct mixin : Y<n> {
int two() { return Y<n>::one() * 2; }
};
int main() {
mixin<1> X;
cout << X.one();
cout << X.two();
return 0;
}
或者:
template <class P>
struct mixin : P {
int two() { return P::one() * 2; }
};
mixin<Y<1>> X;