C++ 11:整数类型的模板函数专业化

And*_*zos 32 c++ templates c++11

假设我有一个模板功能:

template<typename T>
void f(T t)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

我想为所有原始整数类型编写一个专门化.做这个的最好方式是什么?

我的意思是:

template<typename I where is_integral<I>::value is true>
void f(I i)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

并且编译器为整数类型选择第二个版本,为其他所有类型选择第一个版本?

Dav*_*vid 48

使用SFINAE

// For all types except integral types:
template<typename T>
typename std::enable_if<!std::is_integral<T>::value>::type f(T t)
{
    // ...
}

// For integral types only:
template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type f(T t)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

请注意,std::enable_if即使是声明,您也必须包含完整的返回值.

  • 哦,所以它将是`template <class T> typename enable_if <is_integral <T> :: value,X> :: type f(T t)` (3认同)
  • 您已将函数的返回值从void更改为其他值。如果原始函数返回类型怎么办?例如X类?`template &lt;class T&gt; X f(T t)`?那看起来怎么样? (2认同)
  • @ AndrewTomazos-Fathomling`std :: enable_if`的第二个模板参数默认为`void`.这是你的回归类型.我把它保留为默认值,但您可以将其更改为您想要的任何返回类型.您甚至可以使用整数类型返回与非整数类型不同的类型. (2认同)
  • 可以使用`std :: enable_if` [更美观一点](http://rmartinho.github.com/2012/06/01/almost-static-if.html),至少在我的看法. (2认同)

Joh*_*itb 24

我会使用重载决议.这使您不必使用SFINAE总​​体黑客.不幸的是,有许多领域你无法避免它,但幸运的是这不是其中之一.

template<typename T>
void f(T t)
{
  f(t, std::is_integral<T>());
}

template<typename T>
void f(T t, std::true_type)
{ 
  // ...
}

template<typename T>
void f(T t, std::false_type)
{ 
  // ...
}
Run Code Online (Sandbox Code Playgroud)


arn*_*noo 11

使用c ++ 11,std :: enable_if(http://en.cppreference.com/w/cpp/types/enable_if)可以用来做到这一点:

template<typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
void f(T t) {...}
Run Code Online (Sandbox Code Playgroud)

  • 我不喜欢这种方法的是你实际上可以将一个类型传递给第二个模板参数并弄乱SFINAE(与函数的默认第二个参数相同的问题).通过返回类型进行操作是非常简单的.另一方面,对于没有经验的人来说,不清楚函数返回的是什么. (4认同)
  • 这仍然不起作用,因为整数类型将获得2次重载,编译器将无法选择一个. (2认同)

Lig*_*ith 9

这是 C++20 解决方案

template<std::integral T>
void f(T v) {
   ...
}
Run Code Online (Sandbox Code Playgroud)

我认为它实际上是重载函数,但工作原理相同。


mit*_*ull 7

您可以使用可以像这样专门化的帮助程序模板:

#include <string>
#include <iostream>
#include <type_traits>

template <typename T, bool = std::is_integral<T>::value>
struct Foo {
        static void bar(const T& t) { std::cout << "generic: " << t << "\n"; }
};
template <typename T>
struct Foo<T, true> {
        static void bar(const T& t) { std::cout << "integral: " << t << "\n"; }
};

template <typename T>
static void bar(const T& t) {
        return Foo<T>::bar(t);
}

int main() {
        std::string s = "string";
        bar(s);
        int i = 42;
        bar(i);
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

generic: string
integral: 42
Run Code Online (Sandbox Code Playgroud)