【问题标题】:How to iterate through variadic template parameters to create variable number of local variables?如何遍历可变参数模板参数以创建可变数量的局部变量?
【发布时间】:2017-04-02 10:33:15
【问题描述】:

我有许多功能非常相似,但使用不同数量和类型的本地对象运行:

template <class T> T* create1( const std::vector<std::string>& names )
{
    A a( names[0] );
    B b( names[1] );
    C c( names[2] );

    if ( a.valid() && b.valid() && c.valid() )
        return new T( a, b, c );
    else
        return NULL;
}

template <class T> T* create2( const std::vector<std::string>& names )
{
    D d( names[0] );
    E e( names[1] );

    if ( d.valid() && e.valid() )
        return new T( d, e );
    else
        return NULL;
}

create1<ABC>( { "nameA", "nameB", "nameC" } );
create2<DE>( { "nameD", "nameE" } );

可变参数模板能帮助我实现对这些函数的重构吗?

template <class T, typename Args...> T* create()
{
    // loop over Args and create 2 or 3 objects
    // if (....valid())
    //    return T( ... );
    // else
    //    return NULL;
}

create<ABC,A,B,C>( { "nameA", "nameB", "nameC" } );
create<DE,D,E>( { "nameD", "nameE" } );

检查How can I iterate over a packed variadic template argument list?iterating over variadic template's type parameters 没有成功。看不到如何创建数量可变的不同类型的本地对象...

【问题讨论】:

  • 他们需要是本地对象吗?还是临时工好吗?
  • 如果可能的话,我更喜欢本地的,因为实际上它们的创建可能会失败,然后导致函数提前返回。更新了帖子。
  • 你为什么不检查向量名称的大小并做一个 if 语句?您只需一个函数即可完成所有这些操作。这不是可变参数模板的目的。也许你想使用cstdarg
  • std::tuple 有什么问题?
  • @W.F.:没什么,只是没想到 ;-)

标签: c++ c++11 templates variadic-templates


【解决方案1】:

首先,不要把你的名字当作vector。将它们作为参数包。此外,把它们当作你真正想要的东西:

bool is_valid() { return true; }
template <class T, class... Ts>
bool is_valid(T& arg, Ts&... args) {
    return arg.valid() && is_valid(args...);
}

template <class T, class... Args>
T* create(Args&&... args) {
    if (is_valid(args...)) {
        return new T{args...};
    }
    else {
        return nullptr;
    }
}

现在只需传递正确的内容:

create<T>(A{"nameA"}, B{"nameB"}, C{"nameC"});
create<T>(D{"nameD"}, E{"nameE"});

如果出于某种原因,您真的想将类型和名称分开,您也可以这样做:

template <class T, class... Cs, class... As>
T* create_classes(As&&... args) {
    return create<T>(Cs{std::forward<As>(args)}...);
}

【讨论】:

  • 其实没有,我可能把这个例子简化得太多了。请参阅编辑后的帖子,我需要更灵活的东西。
  • 你为什么要把两个参数包带到create_classes
  • @krzaq 这就是 OP 想要的?
  • @Barry 对不起,我没有正确表达我的问题。我只是好奇你为什么要依靠看起来很糟糕的编译器错误消息来告诉用户他们的可变参数包大小不匹配。
  • @krzaq gcc 说“扩展时参数包长度不匹配......”并且 clang 说“包扩展包含参数包......具有不同长度”。这并不比明确的static_assert() 更清楚。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-04
  • 1970-01-01
  • 1970-01-01
  • 2016-12-01
  • 1970-01-01
  • 2019-06-06
相关资源
最近更新 更多