可变参数模板和约束

问题描述 投票:0回答:1

我有一个可变参数模板函数,它将文件名、分隔符和非指定数量的容器作为参数作为列。然后,此函数解析以将所有值归档到表示列的容器中,并在所有值之间放置分隔符。

bool parseToFile (const std::string& file, const char delimiter, auto&... columns)
{
    bool done {false};
    std::ofstream out;
    out.open (file, std::ios::out | std::ios::trunc);
    if (!out)
    {
        done = false;
        std::cout << "SaveFile: Cannot open file: " << file << "!" ;
        std::cout << std::strerror (errno) << std::endl;
    }
    else
    {
        std::size_t maxContainerSize {0};
        auto maxSize = [&maxContainerSize] (std::size_t containerSize)
        {
            maxContainerSize = std::max (maxContainerSize, containerSize);
        };
        (maxSize (columns.size()), ...);
        std::size_t i {0};
        auto implementation = [&i, delimiter, &out] (auto & cont, std::size_t s)
        {
            if (i < cont.size())
                out << cont[i];

            out << delimiter;
        };
        for (; i < maxContainerSize; ++i)
        {
            (implementation (columns, columns.size()), ...);
            out << "\n";
        }
        out << std::flush;
        done = true;
    return done;
}

这可以正确地按预期工作。

但是这个模板有几个与参数包“列”相关的限制

  • 它应该是一个容器
  • 任何容器都应该重载运算符 [] 来访问对象(例如 std::vector、std::deque)
  • 容器中的任何对象都应该有运算符 << to be able to work with iostream

我应该如何更改代码来实现此约束?

我试过这个:

template <template <typename, typename> class Container,
          typename Value,
          typename Allocator = std::allocator<Value>>
concept containerHasPrintable = requires (std::ostream& out, Container<Value,Allocator>& data)
{
    out << data[0];
};

// and definition:
bool parseToFile (const std::string& file, const char delimiter, containerHasPrintable&... columns);

但这不起作用。海湾合作委员会 13.1

main.cpp|80|错误:模板参数数量错误(1,应该至少为 2)| 《80-功能》 main.cpp|40|注意:为“template类Container、类Value、类Allocator>概念containerHasPrintable”|提供《40-概念》 main.cpp|80|错误:扩展模式“int&”不包含参数包|

如何约束模板?

c++ constraints c++20 variadic-templates
1个回答
0
投票

这个:

template <template <typename, typename> class Container,
          typename Value,
          typename Allocator = std::allocator<Value>>
concept containerHasPrintable = /* ... */;

是一个限制三个事物的概念:一个模板和两种类型。但这实际上并不是您想要的 - 您想要一个限制一个事物的概念:类型。

所以你想写的就是:

template <typename Container>
concept PrintableContainer = requires (std::ostream& out, Container& data)
{
    out << data[0];
};

请注意,您的概念中的其他内容实际上都不相关 - 无论如何,您不需要容器特别看起来像

C<V, A>
- 这只是武断地拒绝了一些其他可以工作的类型(例如,
std::string 
)。

© www.soinside.com 2019 - 2024. All rights reserved.