模板结果值应如何正确嵌套在其他模板结构中?

问题描述 投票:0回答:1

我试图根据模板类型 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
成功了...

我缺少什么以及如何解决这个问题?

提前致谢!

c++ templates c++17 type-traits
1个回答
0
投票

两种类型的

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,但可以针对以前的标准重新实现。

© www.soinside.com 2019 - 2024. All rights reserved.