C++ C++;可从任何序列类型初始化的类

C++ C++;可从任何序列类型初始化的类,c++,iterator,C++,Iterator,我想要一个可以从任何序列初始化的类,这意味着可以从任何类型初始化,该类型具有返回迭代器的begin()和end()方法 template<typename B> class A { public: A(any_sequence_type<B> arglist) { for(B b : arglist) init_members(b); } } 模板 甲级 { 公众: A(任意序列类型参数列表) { 对于(B

我想要一个可以从任何序列初始化的类,这意味着可以从任何类型初始化,该类型具有返回迭代器的begin()和end()方法

template<typename B>
class A
{
public:
    A(any_sequence_type<B> arglist)
    {
        for(B b : arglist)
            init_members(b);
    }
}
模板
甲级
{
公众:
A(任意序列类型参数列表)
{
对于(B:arglist)
初始成员(b);
}
}
我希望编译以下内容:

A<int> a = {1, 2, 3};
A<int> b = std::vector<int>();
A<Something> c = MyClassWithBeginAndEnd();
aa={1,2,3};
A b=std::vector();
A c=MyClassWithBeginAnd();
可能吗

编辑:

使用模板构造函数的建议解决方案不起作用。 GCC表示:模板参数推断/替换失败:无法推断模板参数“t”。 Clang说:已忽略候选模板:无法推断模板参数“t”

但是,如果我显式地强制转换初始值设定项,事情就会开始工作

A a = A({B(), B(), B()}); // does not work
A a = (std::initializer_list<B>){B(), B(), B()}; // works
aa=A({B(),B(),B()});//不起作用
A=(std::initializer_list){B(),B(),B()};//作品

为什么会这样?

使用模板构造函数:

template<typename B>
class A
{
public:
    template <typename T>
    A(T&& arglist)
    {
        for (auto&& b : arglist) {
            init_members(b);
        }
    }

    // overload for initializer_list
    A(std::initializer_list<B> arglist) {
        for (auto&& b : arglist) {
            init_members(b);
        }  
    }

};
模板
甲级
{
公众:
模板
A(T&&arglist)
{
用于(自动(&b:arglist){
初始成员(b);
}
}
//初始化器列表的重载
A(std::初始值设定项\列表arglist){
用于(自动(&b:arglist){
初始成员(b);
}  
}
};
如果
T
没有提供
begin
/
end
并且内容不能转换为
B
,则会出现错误

您可以使用SFINAE来限制允许的类型
T
,从而在调用site时出错,而不是在构造函数内部,以防误用


您需要一个模板参数,用于
a::a
接受的类型。如果
Seq
不是合适的序列类型,则应使用SFINAE禁用此构造函数;否则,您将无法通过复制构造函数获得重载解决方案

template <typename Seq,
          typename = std::enable_if_t<
            std::is_convertible<decltype(*std::declval<Seq>().begin()), B>::value &&
            std::is_convertible<decltype(*std::declval<Seq>().end()), B>::value>>
A(Seq arglist) {
    for (B b : arglist) {
        init_members(b);
    }
}
模板>
A(序号arglist){
对于(B:arglist){
初始成员(b);
}
}

也可以考虑使用<代码> const SEQ和而不是<代码> SEQ ,和<代码> const b& b < /> >或<代码> Auto&& b>代码>,而不是<代码> b b>代码>,以避免潜在的昂贵拷贝。


如果您希望它也能与带括号的init列表一起工作,那么必须添加一个单独的
std::initializer\u list
构造函数。这是因为大括号的init列表不是表达式,并且没有类型这基本上总是一个特例。

我也想到了这一点。但这对
aa({1,2,3})不起作用
@mastov:您可以为
std::initializer\u list
创建特定的重载。已编辑并添加了实时演示。模板构造函数不接受初始值设定项列表有什么原因吗?@haael初始值设定项列表没有类型,正如Brian所写:这是因为带括号的init列表不是表达式,也没有类型。Clang说:没有已知的从“std::vector”到“std::initializer\u list”的转换。当我更改时,它在C++11中工作启用\u if\u t启用\u if,但不接受初始值设定项\u列表。