I have for example
#include <iostream>
template <typename T>
struct Base {};
template <>
struct Base<std::string> {
static const int value = true;
};
template <>
struct Base<std::string &> {
static const int value = true;
};
int main() {
bool a = Base<std::string>::value;
bool b = Base<std::string &>::value;
std::cout << a << b << std::endl;
}
https://godbolt.org/z/0NpYxB
Note I have two specializations that are identical and would like to reduce it to one. There are two solutions I know of which I'd prefer not to do.
(1) Remove the reference at the call site so that only one specialization is required.
(2) Create a base class and inherit the reference and no reference versions from that.
Is there a third option where the specialization is generic over reference and non reference types?
C++11 solutions are required.
1) Seems fine:
template <typename T>
struct BaseImpl {};
template <>
struct BaseImpl<std::string> {
static const int value = true;
};
template <typename T>
using Base = BaseImpl<typename std::remove_reference<T>::type>;
2) Seems more verbose
template <typename T>
struct BaseImpl {};
template <>
struct BaseImpl<std::string> {
static const int value = true;
};
template <typename T>
struct Base : BaseImpl<T> {}; // or directly BaseImpl<std::remove_reference_t<T>>
template <typename T>
struct Base<T&> : BaseImpl<T> {};
3) Similar to 2), less verbose, but might be more tricky
template <typename T>
struct Base : Base<T&> {};
template <typename T>
struct Base<T&> {};
template <>
struct Base : Base<std::string> {
static const int value = true;
};
1) seems the more readable, simple to implement.
You can perform the check in SFINAE context:
// type trait to remove the lvalue-reference
template< class T > struct remove_lvalue_reference {typedef T type;};
template< class T > struct remove_lvalue_reference<T&> {typedef T type;};
template <typename T>
using remove_lvalue_reference_t = typename remove_lvalue_reference<T>::type;
template <typename T, typename = void>
struct Base {};
// valid when T is std::string and std::string&
template <typename T>
struct Base<T, typename std::enable_if<std::is_same<std::string, remove_lvalue_reference_t<T>>::value>::type> {
static const int value = true;
};
LIVE
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With