【问题标题】:How to do one explicit specialization for multiple types?如何对多种类型进行一种明确的专业化?
【发布时间】:2011-05-15 20:52:45
【问题描述】:

考虑如下的模板函数,如何为多种类型显式特化一个版本的函数:

template <typename T>
void doSomething(){
 //whatever
}

目的是有一个专业化而不是多个后续专业化,因为 //有些东西是相同的:

void doSomething<int>(){
 //something
}
void doSomething<float>(){
 //something
}
void doSomething<double>(){
 //something
}

有什么方法可以实现一个专业化?

【问题讨论】:

  • 如何调用这些函数来获得所需的专业化?
  • @TokenMacGuy_不要明白你的意思!

标签: c++ templates explicit-specialization


【解决方案1】:

你可以只使用一种 doSomethingImpl 函数。

template<typename T> doSomethingImpl() {
    // whatever
}
template<typename T> doSomething() {
    // something else
}
template<> doSomething<float>() {
    doSomethingImpl<float>();
}
template<> doSomething<int>() {
    doSomethingImpl<int>();
}

还可以进行更通用的专业化,例如使用 SFINAE 和 std::is_numeric&lt;T&gt;

【讨论】:

  • 您仍在为每种类型进行单独的专业化。
  • @Pooria:但您不必分别维护它们的代码。我在回答中说,如果您正在寻找更通用的东西,您可以尝试 std::is_numeric
  • @Puppy 那你能举个例子说明如何使用 std::is_numeric 吗?
【解决方案2】:

你不能使模板函数特化。但是您可以将实现委托给一个辅助类,该类可以从您的函数中使用。一些骨架代码:

实现一个模板类并专门化它:

template< typename T, bool isArithmetic>
struct Something { void operator()() { ... } };

template< typename T, true>
struct Something { void operator()() { ... do something specialized for arithmetic types; } }

然后在模板函数中使用:

template< typename T>
void myFunction()
{
   Something<T, IsArithmetic<T>::value>()();
}

其中 IsArithmetic 是一个提供关于类型 T(选择器)的信息的类。例如,您可以在 boost 库中找到此类类型信息。

【讨论】:

  • 你绝对可以,使用enable_if 和重载。但我同意委托给(专门的)结构通常更干净。
  • @Konrad Rudolph_事实上,唯一的方法似乎是使用 enable_if。
  • @Pooria:是的——“使用enable_if 和重载”是指一种 单一技术,而不是两种不同的技术。还应该注意的是,在幕后,enable_if 只是将 SFINAE 与专门的辅助结构结合使用,就像在 Cătălin 的示例中一样。
【解决方案3】:

使用 c++ 2011(选项 -std=c++11),效果很好:

#include <iostream>

template <typename T>
struct unsignedObject
{
    unsignedObject() {
        std::cout << "instanciate a unsignedObject\n";
    }
};

struct signedObject
{
    signedObject() {
        std::cout << "instanciate a signedObject\n";
    }
};

template <typename T>
struct objectImpl
{
    typedef unsignedObject<T> impl; // optional default implementation (the line can be removed)
};

template <> struct objectImpl<unsigned char>  { typedef unsignedObject<unsigned char>  impl; };
template <> struct objectImpl<unsigned int>   { typedef unsignedObject<unsigned int>   impl; };
template <> struct objectImpl<unsigned short> { typedef unsignedObject<unsigned short> impl; };
template <> struct objectImpl<double>         { typedef signedObject   impl; };
template <> struct objectImpl<int>            { typedef signedObject   impl; };
template <> struct objectImpl<short>          { typedef signedObject   impl; };
template <> struct objectImpl<char>           { typedef signedObject   impl; };

template <typename T>
using object = typename objectImpl<T>::impl;

int main(void)
{
    object<int> x;    // x is a signedObject.
    object<double> y; // y is a signedObject.
    object<unsigned short> z; // z is a unsignedObject.
    return 0;
}

【讨论】:

    猜你喜欢
    • 2011-11-09
    • 2017-03-23
    • 1970-01-01
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    相关资源
    最近更新 更多