我有以下代码片段试图理解 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;
}
Run Code Online (Sandbox Code Playgroud)
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'
Run Code Online (Sandbox Code Playgroud)
知道这是一个已知问题还是我遗漏了什么
从 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;
}
Run Code Online (Sandbox Code Playgroud)
我知道 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;
}
Run Code Online (Sandbox Code Playgroud)
https://godbolt.org/z/W83bYddMT
该解决方案具有相同的目的,适用于其他编译器,并避免添加“true”作为第二个参数。
| 归档时间: |
|
| 查看次数: |
264 次 |
| 最近记录: |