问题
I have this code that specializes the print function for two types, and reverts back to the base version for any other types.
My question is, is there a way to write this without having to type out the negative case for all the specialized versions in the enable_if of the base print function?
i.e. is there a way to remove all the !std::is_same
and still have an unambiguous print function?
Any versions of C++ welcome, but one that works in c++14 would be helpful.
#include <iostream>
template<typename T, std::enable_if_t<!std::is_same<T, int>::value && !std::is_same<T, double>::value, int> = 42>
void print(T data)
{
std::cout << "base:" << data << std::endl;
}
template<typename T, std::enable_if_t<std::is_same<T, double>::value, int> = 42>
void print(T data)
{
std::cout << "double:" << data << std::endl;
}
template<typename T, std::enable_if_t<std::is_same<T, int>::value, int> = 42>
void print(T data)
{
std::cout << "int:" << data << std::endl;
}
int main()
{
std::string foo("foo");
double bar = 1.2;
int baz = 5;
print(foo);
print(bar);
print(baz);
}
回答1:
For your use case, you can simply provide overloads for the print
function as needed
#include <iostream>
template<typename T>
void print(T data)
{
std::cout << "base:" << data << std::endl;
}
void print(double data)
{
std::cout << "double:" << data << std::endl;
}
void print(int data)
{
std::cout << "int:" << data << std::endl;
}
However, if you have more complicated constraints on T
, then you can't specialize print
without explicitly providing the negation of the constraints in the "default" case.
If you have access to c++17, you can write this in a single function. The usual if-else logic means that the base case is only triggered if the "specializations" are not. This avoids having to specify the negations.
template<typename T>
void print(T data)
{
if constexpr(std::is_same<T, double>{})
std::cout << "double:" << data << std::endl;
else if constexpr(std::is_same<T, int>{})
std::cout << "int:" << data << std::endl;
else // if not same as int or double
std::cout << "base:" << data << std::endl;
}
回答2:
One way to avoid complementary conditions is to give an overload priority between overload:
template <std::size_t N> struct priority_overload : priority_overload<N - 1> {};
template <> struct priority_overload<0> {}; // Least priority
and then
template<typename T>
void print(T data, priority_overload<0>) // fallback
{
std::cout << "base:" << data << std::endl;
}
template<typename T, std::enable_if_t<condition1<T>::value, int> = 42>
void print(T data, priority_overload<1>)
{
std::cout << "cond1:" << data << std::endl;
}
template<typename T, std::enable_if_t<condition2<T>::value, int> = 42>
void print(T data, priority_overload<2>)
{
std::cout << "cond2:" << data << std::endl;
}
template<typename T>
void print(T data)
{
print(data, priority_overload<10>{});
// Priority should be greater or equal to the one of possible overloads
}
来源:https://stackoverflow.com/questions/61061842/best-way-to-specialize-function-using-enable-if-for-only-some-types