可选地,支持用于模板的initializer_list构造可以包装容器 [英] Optionally supporting initializer_list construction for templates maybe wrapping containers

查看:98
本文介绍了可选地,支持用于模板的initializer_list构造可以包装容器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有一个包装标准容器的模板,似乎我可以很容易地委托initializer_list构造函数:

If I have a template that wraps a standard container, it seems I can reasonably easily delegate the initializer_list constructor:

template<typename T>
struct holder {
    T t_;

    holder() :
        t_() {}

    holder(std::initializer_list<typename T::value_type> values)
        : t_(values) {}

};

所以这很适合std :: vector。

So this works nicely with std::vector, for instance.

int main(int argc, char* argv[]) {

    holder<std::vector<int>> y{1,2,3};
    return EXIT_SUCCESS;
}

但很显然,T不能作为'int'任何其他没有嵌套value_type typedef的类型。所以,我想使用某种enable_if或类似的技巧,使initializer_list构造函数不被发射,除非T都定义了一个嵌套的value_type typedef,并且可以从std :: initializer_list构造。

But it pretty obviously doesn't work for T as 'int', or any other type that doesn't have a nested value_type typedef. So, I'd like to use some sort of enable_if or similar trick to make the initializer_list constructor not be emitted unless T both defines a nested value_type typedef, and is constructible from std::initializer_list.

我试过下面的,但它仍然不工作,因为编译器(我的情况下clang ++ 3.1)仍然跳过无效的T :: value_type当T是int:

I tried the following, but it still doesn't work, because the compiler (clang++ 3.1 in my case), still trips over the invalid T::value_type when T is int:

holder(typename std::enable_if<std::is_constructible<T, std::initializer_list<typename T::value_type>>::value, std::initializer_list<typename T::value_type>>::type values)
    : t_(values) {}

任何关于如何表达概念的想法给T模板上的初始化列表构造函数超过T的value_type,当且仅当T具有value_type typedef并且可以从initializer_list构造T :: value_type

Any thoughts on how to express the concept "give this template on T an initializer list constructor over T's value_type, if and only if T has a value_type typedef and is constructible from an initializer_list of T::value_type".

推荐答案

SFINAE仅适用于模板参数替换(因此SFINAE中的S)。以下工作:

SFINAE only works on template parameter subsitution(hence the S in SFINAE). The following works:

template<typename T>
struct holder {
    T t_;

    holder() :
        t_() {}

    template<typename U = T>
    holder(typename std::enable_if<std::is_constructible<U, std::initializer_list<typename U::value_type>>::value, 
    std::initializer_list<typename U::value_type>>::type values)
    : t_(values) {}

};

如果你没有使用模板函数,那么整个类将被实例化为 int (在您的示例中),导致编译器错误。

If you didn't use a template function, then the whole class would be instantiated for the type int(in your example), leading to a compiler error.

请注意,如果您使用额外的模板参数,您可以使函数签名更好:

Note that you could make the function signature nicer if you used an extra template parameter:

template<typename U = T, class = typename std::enable_if<std::is_constructible<U, std::initializer_list<typename U::value_type>>::value, bool>::type>
    holder(std::initializer_list<typename U::value_type> values)
    : t_(values) {}

这篇关于可选地,支持用于模板的initializer_list构造可以包装容器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆