从拥抱类型中获取模板参数的值

Getting value of template parameter from embracing type

本文关键字:参数 获取 拥抱 类型      更新时间:2023-10-16

假设我有一个模板类,它有一个整数形参:

template <int N>
class A
{
public:
    static int get_N()
    {
        return N;
    }
};
template<typename T>
class B
{
public:
    B()
    {
        cout << "N = " << T::get_N() << endl; // Accessing N via the auxiliary method
    }
};

要在类B中引用N模板参数,我必须在a中创建一个辅助方法。我希望这样做:

template <int N>
class A
{
};
template<typename T>
class B
{
public:
    B()
    {
        cout << "N = " << T::N << endl; // Accessing N directly
    }
};

问题是我将有很多a模板专门化,我真的不想把这个辅助方法复制到所有的专门化类中,我也不想为此引入继承。有可能实现我想要的吗?

您可以从专门化中推断出该值:

#include <iostream>
template <typename T> struct get_N;
template <template <int N> class T, int N>
struct get_N<T<N>> {
    static constexpr int value = N;
};
template <int N> struct A {};
template <typename T>
struct B {
    void f() { std::cout << get_N<T>::value << 'n'; }
};
int main() {
    B<A<10>>().f();
}

您可以这样提取N:

template<typename A>
struct get_N;
template<int N>
struct get_N<A<N> > : std::integral_constant<int,N> { };

这样,您就不需要在每个A专门化中定义任何内容,但是您可以这样说:

using X = A<3>;
cout << "N = " << get_N<X>() << endl;  // prints: N = 3

然而,我可能仍然更喜欢让A派生一个轻量级模板类,它只定义一个static constrexpr变量,就像juanchopanza的答案一样。然后每个A专门化看起来像

template<>
struct A<3> : A_base<3> { ... };

还不错。事实上,再次查看两个选项,我看到A_base只不过是

template<int N>
using A_base = std::integral_constant<int,N>;

,所以它可以被赋予一个更通用的短名称。我通常叫它num