使用C++ 11 <type_traits>模板参数类型扣除失败

Nor*_*löw 8 c++ type-traits c++11 template-argument-deduction

我试图了解如何使用C++(11)<type_traits>.

这是我的琐碎测试计划

#include <type_traits>

template<class U, class S>
inline U add(typename std::enable_if<std::is_unsigned<U>::value,U>::type a,
             typename std::enable_if<std::is_signed  <S>::value,S>::type b)
{
    return a + b;
}

int main(int argc, const char * argv[], const char * envp[])
{
    unsigned int ui;
    int i;
    auto a = add(ui, i);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

使用GCC 4.8.1编译时,它的错误为

/home/per/f.cpp: In function ‘int main(int, const char**, const char**)’:
/home/per/f.cpp:15:23: error: no matching function for call to ‘add(unsigned int&, int&)’
     auto a = add(ui, i);
                       ^
/home/per/f.cpp:15:23: note: candidate is:
/home/per/f.cpp:5:10: note: template<class U, class S> U add(typename std::enable_if<std::is_unsigned<U>::value, U>::type, typename std::enable_if<std::is_signed<S>::value, S>::type)
 inline U add(typename std::enable_if<std::is_unsigned<U>::value,U>::type a,
          ^
/home/per/f.cpp:5:10: note:   template argument deduction/substitution failed:
/home/per/f.cpp:15:23: note:   couldn't deduce template parameter ‘U’
     auto a = add(ui, i);
                       ^
Run Code Online (Sandbox Code Playgroud)

我不知道为什么GCC无法推断出模板参数U.任何人都知道我的代码丢失了什么信息,那就是我在C++ 11中编写一个程序,它将无符号整数类型作为第一个参数并将有符号整数类型作为第二个参数?

R. *_*des 13

typename std::enable_if<std::is_unsigned<U>::value,U>::type不是可以推断的背景.为了从中推断U,编译器需要能够应用反向操作std::enable_if.它看起来并不太难,这是真的,但那是因为你说的是​​一件简单的事情enable_if.要求每一个特性都是不可能的,所以C++只是玩得很​​酷而且不会产生任何奇怪的规则例外:它一般不可推导,它在这一点上是不可推论的.

你可以这样做:

template<class U, class S,
         EnableIf<std::is_unsigned<U>, std::is_signed<S>>...>
         // see http://flamingdangerzone.com/cxx11/2012/06/01/almost-static-if.html
U add(U a, S b)
Run Code Online (Sandbox Code Playgroud)

或者在不正确支持该样式的编译器中,您只需添加一个额外的默认参数:

template<class U, class S>
U add(U a, S b,
      typename std::enable_if<std::is_unsigned<U>::value
          && std::is_signed<S>::value,void>::type* = nullptr)
Run Code Online (Sandbox Code Playgroud)

......或搞乱返回类型.

template<class U, class S>
typename std::enable_if<std::is_unsigned<U>::value
    && std::is_signed<S>::value,U>::type
add(U a, S b)
Run Code Online (Sandbox Code Playgroud)


And*_*owl 7

你没有给编译器一个推断U和推断的机会S.您可以按如下方式重写函数,并在模板参数列表中移动SFINAE检查:

template<class U, class S,
    typename std::enable_if<std::is_unsigned<U>::value &&
                            std::is_signed  <S>::value
        >::type* = nullptr>
inline U add(U a, S b)
{
    return a + b;
}
Run Code Online (Sandbox Code Playgroud)

这是一个实例.