I can see this topic generates great interest :-) I don't think the motivation is particularly relevant to the problem, but should anyone be interested, it is here
https://github.com/danielaparker/jsoncons/issues/115.
My current attempt introduces a specialization, is_call_traits_specialization, that informs the "library" that type T is already specialized. This does give the desired results:
1 my own vector
2 general sequence container
3 general sequence container
but at the cost of requiring a second template specialization. Comments appreciated.
#include <iostream>
#include <vector>
#include <type_traits>
// library code
namespace ns {
template <class T>
struct is_call_traits_specialization : public std::false_type
{};
template <class J, class T, class Enable=void>
struct call_traits
{
static void f(J val, const T& v)
{
static_assert("No match here");
}
};
// is_sequence_container_of
template <class J,class T, class Enable=void>
struct is_compatible_container : std::false_type {};
template <class J,class T>
struct is_compatible_container<J,T,
typename std::enable_if<!std::is_void<typename std::iterator_traits<typename T::iterator>::value_type>::value
>::type>
: std::true_type {};
template<class J, typename T>
struct call_traits<J, T,
typename std::enable_if<!is_call_traits_specialization<T>::value && is_compatible_container<J,T>::value>::type>
{
static void f(J val, const T& v)
{
std::cout << val << " general sequence container\n";
}
};
} // ns
// user code
struct own_vector : std::vector<int64_t>
{
using std::vector<int64_t>::vector;
};
struct a_vector : std::vector<int64_t> { using std::vector<int64_t>::vector; };
namespace ns {
template <class J>
struct call_traits<J, own_vector>
{
static constexpr bool is_compatible = true;
static void f(J val, const own_vector& v)
{
std::cout << val << " my own vector\n";
}
};
template <>
struct is_call_traits_specialization<own_vector> : public std::true_type
{};
}
int main(int argc, char **argv)
{
ns::call_traits<int64_t, own_vector>::f(1, own_vector());
ns::call_traits<int64_t, a_vector>::f(2, a_vector());
ns::call_traits<int64_t, std::vector<int64_t>>::f(3, std::vector<int64_t>());
}