鉴于模板类A
,我想根据T_res
的模板参数A
和T_lhs
定义类型T_rhs
:
template< typename T_lhs, typename T_rhs >
class A
{
// definition of T_res in case "T_lhs and T_rhs are both not primitive types"
template< bool lhs_is_fundamental = std::is_fundamental<T_lhs>::value,
bool rhs_is_fundamental = std::is_fundamental<T_rhs>::value,
std::enable_if_t<( !lhs_is_fundamental && !rhs_is_fundamental )>* = nullptr >
using T_res = decltype( std::declval<T_lhs>().cast_to_primitive() / std::declval<T_rhs>().cast_to_primitive() );
// definition of T_res in case "T_lhs and/or T_rhs is a primitive type"
template< bool lhs_is_fundamental = std::is_fundamental<T_lhs>::value,
bool rhs_is_fundamental = std::is_fundamental<T_rhs>::value,
std::enable_if_t<( lhs_is_fundamental || rhs_is_fundamental )>* = nullptr >
using T_res = decltype( std::declval<T_lhs>() / std::declval<T_rhs>() );
// ...
};
在第一种情况下,T_lhs
和T_rhs
都不是原始类型,我的代码设计得它们代表实现返回基本类型的函数cast_to_primitive()
的类;在第一种情况下,我希望T_res
具有通过将类型decltype( std::declval<T_lhs>().cast_to_primitive() )
的元素除以decltype( std::declval<T_rhs>().cast_to_primitive() )
类型的元素而获得的类型。
在第二个中,T_lhs
或T_rhs
是基本类型(或两者都是),我希望T_res
具有通过划分类型元素获得的类型T_lhs
类型的元素T_rhs
。例如,如果T_lhs
是基本类型,我的代码就是这样设计的,T_rhs
可以隐式地转换为T_lhs
类型的元素;同样适用于T_rhs
是原始的。
不幸的是,上面的代码无法编译。错误:
error: template non-type parameter has a different type 'std::enable_if_t<(lhs_is_fundamental || rhs_is_fundamental)> *' (aka 'typename enable_if<(lhs_is_fundamental || rhs_is_fundamental), void>::type *') in template redeclaration
std::enable_if_t<( lhs_is_fundamental || rhs_is_fundamental )>* = nullptr >
^
note: previous non-type template parameter with type 'std::enable_if_t<(!lhs_is_fundamental && !rhs_is_fundamental)> *' (aka 'typename enable_if<(!lhs_is_fundamental && !rhs_is_fundamental), void>::type *') is here
std::enable_if_t<( !lhs_is_fundamental && !rhs_is_fundamental )>* = nullptr >
^
有人可以帮我解决问题吗?
答案 0 :(得分:4)
这与Using std::conditional_t
to define a class' typedef
in dependence of its template parameter
解决方案是使用std::conditional
和帮助程序类来延迟实例化cast_to_primitive
的分区/调用,直到实例化std::conditional
之后:
#include <type_traits>
template<class T1, class T2>
struct A
{
template<class T=T1, class U=T2>
struct cast_to_primitive_t {using type=decltype(std::declval<T>().cast_to_primitive() / std::declval<U>().cast_to_primitive());};
template<class T=T1, class U=T2>
struct primitive_div_t {using type=decltype(std::declval<T>() / std::declval<U>());};
using T_res = typename std::conditional_t<std::is_fundamental<T1>{} && std::is_fundamental<T2>{}, primitive_div_t<>, cast_to_primitive_t<>>::type;
};