Reputation: 121
I have following code snippet trying to understand std::enable_if.
Using godbolt I noticed that I worked on almost every compiler (gcc 6.3.0 and onwards) but it does not compile on any version of MSVC (tested on 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 compiler returns:
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'
Any idea if this is a known issue or am I missing something
Removing std::enable_if from bitSize resolves the issue so I assume it has something to do with nested std::enable_if
This code works as example:
#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;
}
Upvotes: 9
Views: 358
Reputation: 121
I understand that MSVC has problems deducing template parameters with std::enable_if
.
In the end, the solution that looks simple and clean would be:
#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
This solution serves the same purpose, works on other compilers and avoids adding 'true' as a second parameter.
Upvotes: 3