Reputation: 153
I have the following code...
#include <iostream>
using namespace std;
template<typename R, R V = R()> R X() { return V; }
int main()
{
cout << boolalpha << X<bool>() << endl;
cout << boolalpha << X<bool, true>() << endl;
cout << X<int>() << endl;
cout << X<int, 5>() << endl;
cout << X<void>() << endl; // compiler error
return 0;
}
...which works for the bool and int cases, but does not compile in the void case. Is there a way to handle this?
I know code like this is acceptable...
void F()
{
return void();
}
...so need to get that behavior out of the template somehow.
Upvotes: 1
Views: 64
Reputation:
You can create an invalid type (None) and specify the return type with type traits:
#include <iostream>
struct None {};
// It may not be reasonable o provide the operator:
inline std::ostream& operator << (std::ostream& stream, None) {
return stream;
}
template<typename R>
struct Traits {
typedef R return_type;
};
template<>
struct Traits<void> {
typedef None return_type;
};
template<typename R>
typename Traits<R>::return_type X() { return typename Traits<R>::return_type(); }
template<typename R, typename Traits<R>::return_type V>
typename Traits<R>::return_type X() { return V; }
int main()
{
std::cout << std::boolalpha << X<bool>() << std::endl;
std::cout << std::boolalpha << X<bool, true>() << std::endl;
std::cout << X<int>() << std::endl;
std::cout << X<int, 5>() << std::endl;
std::cout << X<void>() << std::endl;
return 0;
}
Also, the function X
is split into two, to avoid the problem with the default template parameter.
Upvotes: 0
Reputation: 40623
Use std::enable_if to choose between two function templates. Live Example:
#include <iostream>
#include <type_traits>
using namespace std;
template<typename R, R V = R()>
typename std::enable_if<!is_same<R, void>::value, R>::type X() { return V; }
template<typename R>
typename std::enable_if<is_same<R, void>::value, R>::type X() { return; }
int main()
{
cout << boolalpha << X<bool>() << endl;
cout << boolalpha << X<bool, true>() << endl;
cout << X<int>() << endl;
cout << X<int, 5>() << endl;
X<void>(); // You can't print `void` with standard iostreams...
return 0;
}
Upvotes: 1