在以下示例中,最后一行失败,因为转换运算符JSON必须在两种可能性之间进行选择:
std::vector<int>::operator=(std::vector<int>&&)std::vector<int>::operator=(std::initializer_list<int>)我怎样才能限制JSON::operator T()它忽略initializer_list过载?
struct JSON
{
    using StorageType = std::variant<
        int,
        float,
        std::string,
        std::vector<int>,
        std::vector<float>
    >;
    
    StorageType storage;
    template<class T>
    operator T() const {
        return std::get<T>(storage);
    }
};
int main(int argc, char* argv[])
{
    const JSON json;
    std::vector<int> numbers;
    numbers = json; // more than one operator '=' matches these operands
    return 0;
}
您可以使用enable_if禁用转换initializer_list
template<class>
constexpr inline bool is_initializer_list = false;
template<class T>
constexpr inline bool is_initializer_list<std::initializer_list<T>> = true;
struct JSON
{
    // ...
    template<class T, std::enable_if_t<!is_initializer_list<T>>* = nullptr>
    operator T() const {
        return std::get<T>(storage);
    }
};
虽然如何限制get排除的问题std::initializer_list是合理的,但我认为实际应该检查的是是否是ofT中表示的类型之一。std::variantStorageType
您可以检查某个类型是否包含在 a 的类型列表中,std::variant如下所示:
template <typename T, typename VariantT>
static inline constexpr bool variant_contains_type_v = false;
template <typename T, typename ... Ts>
static inline constexpr bool variant_contains_type_v<T, std::variant<Ts...>> = std::disjunction_v<std::is_same<T, Ts>...>;
然后您的实施可能会适应
template<class T, typename = std::enable_if_t<variant_contains_type_v<T, StorageType>>>
    operator T() const {
    return std::get<T>(storage);
}
https://godbolt.org/z/Pf3x7bEYd
| 归档时间: | 
 | 
| 查看次数: | 117 次 | 
| 最近记录: |