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.
>Solution :
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, ":(");