特定成员的模板专业化?

sol*_*old 24 c++ templates c++-faq specialization

是否可以专门化模板类的特定成员?就像是:

template <typename T,bool B>
struct X
{
    void Specialized();
};

template <typename T>
void X<T,true>::Specialized()
{
    ...
}

template <typename T>
void X<T,false>::Specialized()
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

当然,这段代码无效.

Joh*_*itb 29

您只能通过提供所有模板参数来显式地对其进行专门化.不允许对类模板的成员函数进行部分特化.

template <typename T,bool B>
struct X
{
    void Specialized();
};

// works
template <>
void X<int,true>::Specialized()
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

解决方法是引入重载函数,这些函数仍然属于同一个类,因此它们对成员变量,函数和东西具有相同的访问权限.

// "maps" a bool value to a struct type
template<bool B> struct i2t { };

template <typename T,bool B>
struct X
{
    void Specialized() { SpecializedImpl(i2t<B>()); }

private:
    void SpecializedImpl(i2t<true>) { 
      // ...
    }

    void SpecializedImpl(i2t<false>) { 
      // ...
    }
};
Run Code Online (Sandbox Code Playgroud)

请注意,通过传递重载函数并将模板参数推送到函数参数,您可以任意"专门化"您的函数,也可以根据需要对它们进行模板化.另一种常见技术是遵循单独定义的类模板

template<typename T, bool B>
struct SpecializedImpl;

template<typename T>
struct SpecializedImpl<T, true> {
  static void call() { 
    // ...
  }
};

template<typename T>
struct SpecializedImpl<T, false> {
  static void call() { 
    // ...
  }
};

template <typename T,bool B>
struct X
{
    void Specialized() { SpecializedImpl<T, B>::call(); }
};
Run Code Online (Sandbox Code Playgroud)

我发现通常需要更多的代码,我发现函数重载更容易处理,而其他人更喜欢推迟类模板方式.最后,这是一个品味问题.在这种情况下,你可能已经把其他模板中X也作为嵌套模板-在其他情况下,您明确地专注,而不是只是部分,那么你就不能这样做,因为你只能在命名空间内放置明确的专业化,不进入课堂范围.

你也可以创建这样一个SpecializedImpl模板只是为了函数重载的目的(它的工作方式类似于i2t之前的),如下面的变量演示了第一个参数变量也是如此(所以你可以用其他类型调用它 - 不仅仅是当前实例化的模板参数)

template <typename T,bool B>
struct X
{
private:
    // maps a type and non-type parameter to a struct type
    template<typename T, bool B>
    struct SpecializedImpl { };

public:
    void Specialized() { Specialized(SpecializedImpl<T, B>()); }

private:
    template<typename U>
    void Specialized(SpecializedImpl<U, true>) {
      // ...
    }

    template<typename U>
    void Specialized(SpecializedImpl<U, false>) {
      // ...
    }
};
Run Code Online (Sandbox Code Playgroud)

我有时觉得,推迟到另一个模板是更好的(当它涉及到此类案件的数组和指针,超载可能非常棘手,只是转发给类模板为我如此简单的话),有时只是超载内的模板是更好 - 特别是如果你真的转发函数参数,并且你触摸类的成员变量.


Ara*_*raK 3

这是我想出来的,还不错:)

//The generic template is by default 'flag == false'
template <class Type, bool flag>
struct something
{
    void doSomething()
    {
        std::cout << "something. flag == false";
    }
};

template <class Type>
struct something<Type, true> : public something<Type, false>
{
    void doSomething() // override original dosomething!
    {
        std::cout << "something. flag == true";
    }
};

int main()
{
    something<int, false> falseSomething;
    something<int, true> trueSomething;

    falseSomething.doSomething();
    trueSomething.doSomething();
}
Run Code Online (Sandbox Code Playgroud)

  • 你没有凌驾于一切之上,你只是在隐藏。 (6认同)