Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何编写一个函数,该函数采用;嵌套的;模板类型作为参数_C++_C++17 - Fatal编程技术网

C++ 如何编写一个函数,该函数采用;嵌套的;模板类型作为参数

C++ 如何编写一个函数,该函数采用;嵌套的;模板类型作为参数,c++,c++17,C++,C++17,我想编写一个通用函数,它采用一些类似于map的类型,并返回map中的所有键。我还希望函数的API非常简单,如下所示: std::unordered_map<int, std::string> stringTable; auto stringTableKeys = keys(stringTable); // should return a std::vector<int> std::map<std::string, double> doubleTable; a

我想编写一个通用函数,它采用一些类似于map的类型,并返回map中的所有键。我还希望函数的API非常简单,如下所示:

std::unordered_map<int, std::string> stringTable;
auto stringTableKeys = keys(stringTable); // should return a std::vector<int>

std::map<std::string, double> doubleTable;
auto doubleTableKeys = keys(doubleTable); // should return a std::vector<std::string>
std::无序映射字符串表;
自动stringTableKeys=键(stringTable);//应该返回一个std::vector
std::map双表;
自动双表键=键(双表);//应该返回一个std::vector
我不希望它绑定到std::map或std::unordered_map,也不希望绑定到特定的键或值类型,因此我尝试编写以下内容:

template <typename Key, typename Value, template <typename, typename...> typename Table>
std::vector<Key> keys(const Table<Key, Value>& table)
{
    std::vector<Key> keys;
    keys.reserve(table.size());
    for (const auto& [key, value] : table)
        keys.push_back(key);
    return keys;
}
模板
标准::向量键(常数表和表)
{
向量键;
keys.reserve(table.size());
用于(常数自动和[键,值]:表)
按键。向后推(按键);
返回键;
}
但是,如果我想使用这个版本的keys()函数,我必须这样调用它

auto stringTableKeys = keys<int, std::string, std::unordered_map>(stringTable);
自动stringTableKeys=键(stringTable);

如何在keys()的定义中指定模板,以便调用方不必指定类型?

很抱歉造成混淆,事实证明我的代码确实有效。

这只是Visual Studio 2019中的一个bug,我不确定它是否能正常工作,因为它说这是一个语法错误:

您介绍的代码。然而,它也有一些问题

如果输入映射类型使用不同于默认值的模板参数,它将无法编译。这是因为
签名不会推导出
的模板参数,前两个参数除外。例如,这样调用
键将失败:

std::map<int, std::string, std::greater<int>> stringTable;
auto stringTableKeys = keys(stringTable); // the deduced type of table argument
                                          // does not match that of stringTable

这是我的建议

但是,如果参数的类型与预期的
template typename表
签名不匹配(其中第一个模板参数表示密钥类型),则仍会中断。为了缓解这种情况,可以使用由所有关联容器定义的嵌套
key\u类型
value\u类型
类型。例如:

template <typename Container>
std::vector<typename Container::key_type> keys(const Container& table)
{
    std::vector<typename Container::key_type> keys;
    keys.reserve(table.size());
    for (const auto& [key, value] : table)
        keys.push_back(key);
    return keys;
}
模板
std::向量键(常量容器和表)
{
向量键;
keys.reserve(table.size());
用于(常数自动和[键,值]:表)
按键。向后推(按键);
返回键;
}
或:

模板
std::vector>
键(常量容器和表)
{
std::vector>键;
keys.reserve(table.size());
用于(常数自动和[键,值]:表)
按键。向后推(按键);
返回键;
}
请注意,所有关联容器的
Container::value_type
都是
std::pair
,并且
std::pair
定义了
第一个_type
第二个_type
嵌套的typedef以访问其元素类型。我们需要使用
std::remove_const_t
来消除键类型的
const
限定


后一版本的
keys
特别有用,因为它不仅适用于关联容器,还适用于
std::pair
s的任何序列。查看代码。

如果您的函数已经依赖于您编写的基于范围的
for
循环正确工作的假设,我不确定您是否会因为使用
键类型而失去更多的通用性。例如,只需将
MapType
作为类模板参数,并返回
std::vector
。我是否遗漏了什么;您的尝试似乎是?这是您生成代码时的编译器错误,还是IDE中出现错误?@cigien没有编译器错误,只有IDE错误。我在您的屏幕截图中没有看到任何显示“语法错误”的内容,只有一些。让您的编译器拥有最终决定权,而不是不一致的感觉。:)
template <typename Container>
std::vector<typename Container::key_type> keys(const Container& table)
{
    std::vector<typename Container::key_type> keys;
    keys.reserve(table.size());
    for (const auto& [key, value] : table)
        keys.push_back(key);
    return keys;
}
template <typename Container>
std::vector<std::remove_const_t<
    typename Container::value_type::first_type>>
    keys(const Container& table)
{
    std::vector<std::remove_const_t<
        typename Container::value_type::first_type>> keys;
    keys.reserve(table.size());
    for (const auto& [key, value] : table)
        keys.push_back(key);
    return keys;
}