I am trying to create a function and constrain it to is_trait_type
s which is defined as:
template <typename T>
struct is_trait_type : std::false_type
{
};
template <>
struct is_trait_type<my_type> : std::true_type
{
};
I want to provide a default implementation for all is_trait_type
s and then using partial specialization custom behavior for other_type
s (which obviously are also is_trait_type
s.
This is the function in question:
// default impl for all is_trait_types
template <typename T, std::enable_if_t<is_trait_type<T>{}, int> = 0>
inline bool should_delay_aggregation(typename T::aggregation, const typename T::type&)
{
return false;
}
// partial specialization for other_types
template<>
inline bool should_delay_aggregation<other_type>(other_type::aggregation, const other_type::type&)
{
return some logic with aggregation and type;
}
But I can't get it to compile I get the classic template-id ‘should_delay_aggregation<other_type>’ for ‘bool should_delay_aggregation(other_type::aggregation, const other_type::type&)’ does not match any template declaration
, candidate is: ‘template<class T, typename std::enable_if<is_trait_type<T>{}, int>::type <anonymous> > bool should_delay_aggregation(typename T::aggregation, const typename T::type&)
I do need to use std::enable_if
since I using C++14. I know that with concepts this would be much easier, but I am not too familiar with std::enable_if
.
Thanks in advance.
There are no partial specializations of function templates (Why function template cannot be partially specialized?), and even if there were, you wouldn't be using the right syntax.
You could write a full specialization of a function template:
template <typename T>
auto should_delay_aggregation(typename T::aggregation, const typename T::type&)
-> std::enable_if_t<is_trait_type<T>{}, bool>
{
return false;
}
// note: if you remove template <>, this simply becomes an overload instead
// of a full specialization, which is also okay
template <>
bool should_delay_aggregation(other_type::aggregation, const other_type::type&)
{
return /* ... */;
}
However, this isn't very idiomatic; type traits are usually implemented as a class for multiple reasons, and this would also allow you to avoid std::enable_if_t
:
template <bool B> // use std::bool_constant in C++17
using bool_constant = std::integral_constant<bool, B>;
// primary template
template <typename T>
struct should_delay_aggregation : bool_constant<std::is_same<T, my_type>::value> {};
// note: is_trait_type can be simplified to std:is_same<T, my_type>
// full specialization for other_type
template <>
struct should_delay_aggregation<other_type> : bool_constant</* some logic here */> {};
// other partial specializations are also possible ...
// usage:
static_assert(should_delay_aggregation<other_type>::value, ":(");