c++ std::enable_if在MSVC编译器中无法正常工作

qojgxg4l  于 2022-12-27  发布在  其他
关注(0)|答案(1)|浏览(225)

我有以下代码片段试图理解std::enable_if。
使用godbolt时,我注意到我在几乎所有编译器(gcc 6.3.0及更高版本)上都做过工作,但它不能在任何版本的MSVC上编译(在MSVC 2015、2017、2019上测试)。

#include <cstdint>
#include <iostream>

template <typename T, typename std::enable_if<(std::is_arithmetic<T>::value), bool>::type = true>
constexpr std::size_t bitSize()
{
    return sizeof(T) * 8;
}

template <typename T, typename std::enable_if <(bitSize<T>() == 8), bool>::type = true>
void f(T val) {
    std::cout << "f val = " << val << std::endl;
}

int main()
{
    uint8_t u8 = 1;
    f<uint8_t>(u8);
    
    return 1;
}

MSVC编译器返回:

main.cpp(10,49): error C2672: 'bitSize': no matching overloaded function found
main.cpp(5,23): message : could be 'size_t bitSize(void)'
main.cpp(10,60): message : 'size_t bitSize(void)': could not deduce template argument for '__formal'
main.cpp(18,2): error C2672: 'f': no matching overloaded function found
main.cpp(11,6): message : could be 'void f(T)'
main.cpp(18,15): message : 'void f(T)': could not deduce template argument for '__formal'

是否知道这是一个已知问题或者我遗漏了什么
从bitSize中删除std::enable_if解决了这个问题,所以我假设它与嵌套的std::enable_if有关
此代码的工作原理如下:

#include <cstdint>
#include <iostream>

template <typename T>
constexpr std::size_t bitSize()
{
    return sizeof(T) * 8;
}

template <typename T, typename std::enable_if <(bitSize<T>() == 8), bool>::type = true>
void f(T val) {
    std::cout << "f val = " << val << std::endl;
}

int main()
{
    uint8_t u8 = 1;
    f<uint8_t>(u8);
    
    return 1;
}
yi0zb3m4

yi0zb3m41#

我知道MSVC在使用std::enable_if推导模板参数时存在问题。
最后,看起来简单明了的解决方案是:

#include <cstdint>
#include <iostream>

template <typename T>
constexpr typename std::enable_if<(std::is_arithmetic<T>::value), std::size_t>::type bitSize()
{
    return sizeof(T) * 8;
}

template <typename T>
typename std::enable_if <(bitSize<T>() == 8)>::type f(T val) {
    std::cout << "f val = " << val << std::endl;
}

int main()
{
    uint8_t u8 = 'a';
    f<uint8_t>(u8);
    
    return 1;
}

https://godbolt.org/z/W83bYddMT
此解决方案的用途相同,适用于其他编译器,并避免添加“true”作为第二个参数。

相关问题