首页 > 解决方案 > 如果我可以从 std::vector.front() 获得非常量引用,则启用模板

问题描述

我确实有一个像这样的通用容器:

template<typename T>
struct GenericContainer
{
    T& at(size_t index)
    {
        return data.at(index);
    }

    void append(const T& value)
    {
        data.push_back(value);
    }

    std::vector<T> data;
};

众所周知,我们无法通过 std::vector.at 函数获得对 bool 的非 const 引用。
所以这不会编译: bool& b = std::vector<bool>(true).front()

出于同样的原因,我不能在我的 GenericContainer 上调用该函数。

只有当我可以获得对 T 的非 const 引用时,我才想在我的 GenericContainer 上启用该功能。

我试图实现这样的类型特征,但它不起作用,它返回 bool 和 int 的 true_type,我正在寻找 bool 的 false_type 和 int 的 true_type。
它的灵感来自 is_copy_assignable 类型特征。

template <typename T>
struct is_ref_extractable_from_vector
{
    private:
    template <class U, class ENABLED = decltype(std::declval<U&>() = std::declval<std::vector<U>>().front())>
    static std::true_type try_assignment(U&&);
    static std::false_type try_assignment(...);

    public:
    using type = decltype(try_assignment(std::declval<T>()));
};


template<typename T>
using is_ref_assignable_from_vector_t = typename is_ref_extractable_from_vector<T>::type;

template <typename T>
inline constexpr bool is_ref_assignable_from_vector_v = is_ref_assignable_from_vector_t<T>::value;

static_assert(!is_ref_assignable_from_vector_v<bool>);
static_assert(is_ref_assignable_from_vector_v<int>);

我不知道为什么 enable_if 子句中的赋值总是编译。
我正在跳过 SFINAE 以丢弃带有 U = bool 的 try_assignment(U&&) 重载。

谢谢你的帮助。

ps:请注意,我在元编程方面有点新手,所以如果这个结果有明显的原因,我不会感到惊讶:)

标签: c++typetraits

解决方案


只有那个 std::vector<bool>损坏的规范,所以写你的特征最简单的方法是

template <typename T>
struct is_ref_extractable_from_vector : std::true_type {};

template <>
struct is_ref_extractable_from_vector<bool> : std::false_type {};

或者,您可以专门GenericContainer研究bool它不使用std::vector<bool>

class vector_bool {
    // all the members of std::vector

private:
    bool * data;
    std::size_t size;
    std::size_t capacity;
};

template<>
struct GenericContainer<bool> {
    bool& at(size_t index)
    {
        return data.at(index);
    }

    void append(const bool& value)
    {
        data.push_back(value);
    }

    vector_bool data;
}

推荐阅读