在专用和非专用模板化结构之间共享代码

时间:2016-04-14 17:12:37

标签: c++ templates

我如何在专用和非专业版的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查找调用?

3 个答案:

答案 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;