根据模板类型有条件地删除变量

时间:2019-12-23 14:34:39

标签: c++ templates

当前,我正在使用如下所示的代码。

template<class T, class U = char>
struct ScoredObject {
    ScoredObject( T *object, double score, const U &data = U() ) noexcept( noexcept( U( data ) ) ) : object( object ), score( score ), data( data ) {}
    T *object;
    double score;
    U data;
    // ...
};

在所有情况下,除1外,不使用data变量。默认为char,以便尽可能少地浪费空间。实际上,我希望它是void,但当然它不会编译。

我知道我可以在构造函数上执行一些std::enable_if,但是问题仍然是data变量。当dataU时,是否可以使用某种模板“魔术”来删除void变量?

基本上,我想做这样的事情(我知道这是无效的)

template<typename f = U, typename std::enable_if<!std::is_void<f>::value, bool>::type = true>
U data;

1 个答案:

答案 0 :(得分:1)

您可以根据Scored_object的类型从不同的基础继承U。像这样:

template<class T, class U>
struct Scored_object_base : Scored_object_base<T, void> {
    U data;

    using Base = Scored_object_base<T, void>;
    Scored_object_base(T* object, double score, const U& data)
        : Base(object, score), data(data) {}
};

template<class T>
struct Scored_object_base<T, void> {
    T* object;
    double score;

    Scored_object_base(T* object, double score) 
        : object(object), score(score) {}
};

template<class T, class U = void>
struct Scored_object : Scored_object_base<T, U> {
    using Base = Scored_object_base<T, U>;
    using Base::Base;
};

template<class T, class U>
bool operator==(const Scored_object<T, U>& o1, const Scored_object<T, U>& o2) {
    const auto f = (*o1.object == *o2.object && o1.score == o2.score);
    if constexpr (std::is_void_v<U>)
        return f;
    else
        return f && o1.data == o2.data;
}

int main() {
    int i;
    Scored_object<int, void> o1(&i, 1);
    Scored_object<int, char> o2(&i, 1, 'a');

    std::cout << sizeof(o1) << std::endl;   // Output: 16
    std::cout << sizeof(o2) << std::endl;   // Output: 24
}