我试图根据模板类型 T 有条件地选择类型 Res。 条件是如果 T 具有特定的成员类型(用
using
声明),则将 Res 设置为该成员类型。否则,将 Res 设置为其他类型。
这可以通过 std::conditional 类型特征(成功)完成。
当我想在不同的模板类中使用 Res 作为成员类型(也用
using
声明)时,我遇到了问题。
#include <experimental/type_traits>
template<typename T>
class DifferenceData;
template<class T>
using hasDifferenceType = typename T::DifferenceType;
template<typename T>
struct MyDifferenceType {
using DifferenceType = typename std::conditional<std::experimental::is_detected<hasDifferenceType, T>::value,
typename T::DifferenceType, DifferenceData<T>>::type;
};
class IntegerDifferenceData;
class Integer {
public:
using DifferenceType = IntegerDifferenceData;
};
class String {
};
template<typename T>
class DifferenceData {
public:
};
class IntegerDifferenceData : public DifferenceData<Integer> {
};
int main() {
static_assert(std::experimental::is_detected<hasDifferenceType, Integer>::value);
static_assert(!std::experimental::is_detected<hasDifferenceType, String>::value);
static_assert(std::is_same<typename MyDifferenceType<Integer>::DifferenceType, IntegerDifferenceData>::value);
// The line below produces an error: "no type named 'DifferenceType' in 'class String'"
// static_assert(std::is_same<typename MyDifferenceType<String>::DifferenceType, DifferenceData<String>>::value);
return 0;
}
在代码示例中,Integer类定义了
DifferenceType
,而String没有定义。
MyDifferenceType 实现上述条件:如果模板参数定义了此成员类型,则使用定义的 DifferenceType
,否则使用默认的 DifferenceData<T>
类型。
取消注释最后一个
static_assert
时出现的错误是“‘class String’中没有名为‘DifferenceType’的类型”。
我不明白为什么会发生这种情况,因为之前检查 String未定义
static_assert
的 DifferenceType
成功了...
我缺少什么以及如何解决这个问题?
提前致谢!
两种类型的
std::conditional
都应该存在,您可能会通过额外的间接方式来延迟解析
// helper to have name "type" as for std::type_identity
template<class T>
struct DifferenceTypeT
{
using type = typename T::DifferenceType;
};
template <typename T>
struct MyDifferenceType {
using DifferenceType =
typename std::conditional_t<
std::experimental::is_detected<hasDifferenceType, T>::value,
DifferenceTypeT<T>,
std::type_identity<DifferenceData<T>>>::type;
};
std::type_identity
是 C++20,但可以针对以前的标准重新实现。