8

在下面的代码片段中,

template<typename T1>
void func(T1& t)
{
    cout << "all" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "float" << endl;
}

// I do not want this
// template<> void func(float &t)

int main()
{
    int i; float f;
    func(i); // should print "all"
    func(f); // should print "float" 
    return 0;
}

我想修改模板,通过传递除浮点数以外的任何类型将打印“全部”,传递浮点数将打印“浮点数”。我不想要模板专业化,而是有部分专业化,它将根据输入类型相应地采取行动。我该怎么做。提前致谢。

好吧,我目前面临的情况是,我需要定义以下内容,

template<typename T1>
void func(T1 &t)
{
    cout << "t1" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "t2" << endl;
}

以下调用应打印“t2”

func(int) // print "t2"
func(float) // print "t2"
func(string) // print "t2"

以下调用应打印“t1”

func(char) // print "t1"
func(xyz) // print "t1"
...
func(abc) // print "t1"

像上面这样的某种分组,其中很少有人应该调用部分专业化实现,而其他人应该调用默认实现。

4

5 回答 5

12

您可以将函数重载与模板结合使用。所以:

#include <iostream>

template<typename T>
void func(T& t)
{
    std::cout << "all" << std::endl;
}

void func(float& f)
{
    std::cout << "float" << std::endl;
}

int main()
{
    int i; float f;
    func(i); // prints "all"
    func(f); // prints "float" 
    return 0;
}
于 2011-02-15T10:51:10.803 回答
6

您不能在 C++ 中部分专门化函数。

也许这不是你的意思。您可以使用模板,例如boost::is_same<T1, T2>根据给定的模板参数执行条件逻辑。您还可以T在任何需要使用任何其他类型的地方使用,例如typeid(T).name()

template <typename T>
void foo(T&) {
   if (boost::is_same<T, int>::value)
      std::cout << "int lol";
   else
      std::cout << typeid(T).name();
}

(虽然我不建议使用 typeid().name() ,因为它的值不是由标准指定的,并且可能会因代码中编写的类型、损坏的符号或Pokerface的歌词而异。)

附录像其他回答者一样,我个人会选择模板专业化本身或只是简单的函数重载。我不知道你为什么反对他们,但这就是他们的目的。

于 2011-02-15T10:44:49.957 回答
6

为您的条件编写一个类型特征类:

template<class T>
struct IsIntFloatOrString {
  enum { value = boost::is_same<T, int>::value
              or boost::is_same<T, float>::value
              or boost::is_same<T, string>::value };
};

使用boost::enable_if和 disable_if:

template<typename T1>
typename boost::enable_if<IsIntFloatOrString<T1> >::type
func(T1 &t) {
  cout << "t1" << endl;
}

template<typename T2>
typename boost::disable_if<IsIntFloatOrString<T2> >::type
func(T2 &t) {
  cout << "t2" << endl;
}
于 2011-02-15T21:16:22.000 回答
3

正如 Tomalak 在他的回答中已经说过的那样,您不能部分专门化模板函数,但是如果您将函数更改为模板类中的静态成员函数,则可以这样做。

但是,更好的方法是函数重载。

于 2011-02-15T10:56:31.730 回答
0

这是在任意数量的条件下如何使其在没有丑陋语法a and !b and !c的情况下工作的方法。enable_if

如果我们知道偏特化不是工作函数而是使用类,那么让我们使用类吧!我们应该对人们隐藏它,但我们可以使用它们!

好的,代码:

#include <type_traits>
#include <iostream>


template <typename T>
class is_int_or_float : public std::integral_constant<bool, std::is_same<T, int>::value || std::is_same<T, float>::value> {
};


template<typename T, typename Enable = void> //(2)
struct Helper {
    static void go(const T&) {
                std::cout << "all"<< std::endl;
        }
};

template<typename T>
struct Helper<T, typename std::enable_if<is_int_or_float<T>::value>::type> { // (3)
        static void go(const T&) {
                std::cout << "int or float" << std::endl;
        }
};

template<typename T>
struct Helper<T, typename std::enable_if<std::is_pointer<T>::value>::type> { // (3)
        static void go(const T&) {
                std::cout << "pointer" << std::endl;
        }
};

template<typename T>
void func(const T& arg) {
        Helper<T>::go(arg); // (1)
}
int main() {
        char c;
        int i;
        float f; 
        int* p;
        func(c);
        func(i);
        func(f);
        func(p);
}

(1) 首先只针对每种类型的调用助手。没有专门的功能。
(2) 这里我们添加一个虚拟参数。我们不必在调用时指定它,因为它默认为void (3) 在 3 中void,当我们允许时,我们只给出 ,T以及其他任何东西(或在我们的例子中为 SFINAE)。一件重要的事情是我们不应该允许T两次或更多。

笔记:

  1. 我们还可以将默认类型更改为 std::true_type,之后我们将能够摆脱std::enable_ifstd::enable_if<some_trait<T>::value>将更改为 just some_trait<T>::type)。我不确定哪个

  2. 此代码使用 C++11 中的类型特征。如果您没有 c++11 支持,您可以编写自己的特征或使用类型特征boost

活生生的例子

于 2013-08-18T19:35:17.577 回答