Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++11:整数类型的模板函数专门化_C++_Templates_C++11 - Fatal编程技术网

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

C++11:整数类型的模板函数专门化,c++,templates,c++11,C++,Templates,C++11,假设我有一个模板函数: template<typename T> void f(T t) { ... } 我想为所有原始整数类型编写一个专门化。最好的方法是什么 我的意思是: template<typename I where is_integral<I>::value is true> void f(I i) { ... } 编译器为整数类型选择第二个版本,为其他所有类型选择第一个版本?使用c++11,std::enable\u如果可以这

假设我有一个模板函数:

template<typename T>
void f(T t)
{
    ...
}
我想为所有原始整数类型编写一个专门化。最好的方法是什么

我的意思是:

template<typename I where is_integral<I>::value is true>
void f(I i)
{
    ...
}

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

使用c++11,std::enable\u如果可以这样做:

template<typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
void f(T t) {...}
使用


您可以使用一个助手模板,该模板可以专门化为:

#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;
}

我会使用超负荷分辨率。这样你就不用再使用斯芬纳黑客了。不幸的是,有许多方面你无法避免,但幸运的是,这不是其中之一

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)
{ 
  // ...
}

通过在函数体中实现不同的版本来实现更简单、可读性更好的方法怎么样

    template<typename T>
    void DoSomething(T inVal) {
        static_assert(std::is_floating_point<T>::value || std::is_integral<T>::value, "Only defined for float or integral types");
        if constexpr(std::is_floating_point<T>::value) {
            // Do something with a float
        } else if constexpr(std::is_integral<T>::value) {
            // Do something with an integral
        }
    }
你不必担心性能。这些条件是编译时常量,下降编译器将优化它们。
如果不幸的是,constexpr是c++17,但当两个版本都编译时,两种类型都没有错误时,您可以删除constexpr

c++11中的函数是否有模板专用化?我认为在C++03中,它只是重载。我一直在寻找类似的东西,但失败了。我所能做的就是定义一个标准模板,然后在里面检查给定的参数是否是整数type@AlexanderChertovC++03中有,但是。这同样适用于C++11。@AlexanderChertov:是的,函数模板即使在C++03中也可以专门化,但不能部分专门化。这仍然不起作用,因为整型会有两个重载,编译器将无法选择一个。我不喜欢这个方法的地方是,你实际上可以将一个类型传递给第二个模板参数,然后用默认的第二个参数来处理SFINAE同样的问题。通过返回类型执行此操作是傻瓜式的。另一方面,对于未初始化的人来说,不清楚函数返回什么。您已经将函数的返回值从void更改为其他值。如果原始函数返回一个类型怎么办?例如X类?模板X英尺t?如果::type为void,如果只给出1个模板参数,那么它会是什么样子?@AndrewTomazos Fathomling,std::ebable_;或第二个模板参数。@AndrewTomazos正在研究std::enable_的第二个模板参数,如果默认为void。那是你的回报类型。我将其保留为默认值,但您可以将其更改为您想要的任何返回类型。您甚至可以让整型类型返回与非整型类型不同的类型。哦,如果::type fT tIt可以使用std::enable_,那么模板typename enable_应该是这样的,至少在我看来是这样的。对于类模板委托,+1,因为这不仅允许显式的,而且允许部分专门化。这也符合Sutter&Alexandrescu编码标准第66项:不要专门化函数模板。@rhalbersma我喜欢这个答案,但我认为你的推理不合理。这里没有答案使用函数模板专门化。对于这个问题,使用函数模板专门化并不是一个切实可行的选择。问题本身要求专门化。@Dave尽管您的答案在技术上是正确的,但SFINAE是一个使用过度且潜在危险的工具。函数模板专门化和SFINAE都依赖于难以调试的函数重载解析效果。使用标记分派通常更容易,例如,对于多个备选方案,对于非模板函数或委托给类专门化,也可以使用部分专门化的形式。是的,我同意。我对这个答案投了赞成票,实际上我认为它比我自己的答案要好。但我有不同的理由。我喜欢它,因为对函数的用户来说,签名看起来是正确的,没有疯狂的返回类型,他们不确定实际类型是什么。这两种类型都需要://使用浮点编译非浮点T,使用整型编译非整型T;或者如果constexpr在2012年被问及这个问题时并不存在,那么你的意思是,在2012年,编译器会一直尝试为任何类型编译两个版本,即使它可能已经在编译时丢弃了错误的版本?两个版本?是的,你有一个if语句。这两个分支必须是合法的C++语句。这正是如果constexpr是为Question is创建的,而Question is没有if constexpr。
generic: string
integral: 42
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)
{ 
  // ...
}
    template<typename T>
    void DoSomething(T inVal) {
        static_assert(std::is_floating_point<T>::value || std::is_integral<T>::value, "Only defined for float or integral types");
        if constexpr(std::is_floating_point<T>::value) {
            // Do something with a float
        } else if constexpr(std::is_integral<T>::value) {
            // Do something with an integral
        }
    }