【问题标题】:Send type into function using templates使用模板将类型发送到函数中
【发布时间】:2021-02-04 07:54:06
【问题描述】:

我有这个函数可以在 map 中查找键并返回正确的值:

template< typename T >
T Foo::findInMap(std::string key) {
    std::map<std::string, std::any>::iterator it = options.find(key);
    if (it != options.end())
    {
        return std::any_cast<T>(it->second);
    }
    return nullptr;
}

地图如下所示:

std::map<std::string, std::any> options;

如何调用和修改函数以充分利用 C++17?

【问题讨论】:

  • 这不是 C++17 而是“C++98”:您也许可以将标准构造的 T 变量的地址提供给查找函数,而不是按值返回它。因此,可以使用 bool 返回而不是 nullptr,由于当前的返回类型规范(可能是错字?),这也将不起作用。
  • std::optional 是 C++17
  • 这不是代码审查,我是 c++17 的新手

标签: c++ templates c++17


【解决方案1】:

返回nullptr 并不总是可行的。返回可选值的现代 C++ 方法是使用std::optional。您可以使用 auto 代替长迭代器类型名称。这是您可以做到的一种方法:

template< typename T >
std::optional<T> findInMap(std::string key) {
    auto const it = options.find(key);
    if (it != options.end())
        return std::optional<T>{ std::any_cast<T>(it->second) };
    return std::nullopt;
}

【讨论】:

  • 你能说明一下如何调用它吗?
  • 如果想要“完整的 C++17”,那么std::optional 的 CTAD 也是可能的。而it 可以在if 的可选init 语句中定义。
  • 非常感谢。虽然我仍然认为如果包括在内,这不会损害您的答案:-)
【解决方案2】:

对于同时声明和初始化,std::optional 可能会提供更好的方法。但是在任何情况下,类型可变性和可选性都会影响上下文(阅读:调用和案例区分)。我决定承担使用默认初始化的变量加载周围范围的成本,以便在找到的情况下随后被覆盖。这样我就得到了一个函数调用,它的参数决定了类型,使得调用者不需要尖括号中的类型说明。

我还将函数重命名为map_assign(删除了成员函数状态,因为这里不相关):

template< typename T >
bool map_assign(const std::string& key, T* value) {
    auto it = options.find(key);
    if (it != options.end())
    {
        *value = std::any_cast<T>(it->second);
        return true;
    }
    return false;
}

你可以这样称呼它:

std::string value;
if (map_assign("somekey", &value)) {
    // found case
} else {
    // not-found case
}

【讨论】:

  • 谢谢,为什么要在 any_cast 中使用指针?我可以在没有指针的情况下通过 ref 返回就好了
  • 谢谢,我还修复了一个问题。我本可以通过引用来实现它,但这只是一个风格细节,并且我个人经历了一个高度依赖于引用的阶段,我目前更倾向于指针版本。
【解决方案3】:

any_cast(T&) 抛出 std::bad_any_cast,改用 any_cast(const T*)

struct Test {
  template <typename T>
  std::optional<T> findInMap(std::string key) {
    if (auto it = options.find(key); it != options.end()) {
      if(auto ptr = std::any_cast<T>(&it->second); ptr) {
        return std::make_optional<T>(*ptr);
      }
    }
    return std::nullopt;
  }

  std::map<std::string, std::any> options;
};

【讨论】:

    猜你喜欢
    • 2012-03-27
    • 1970-01-01
    • 2011-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-10
    相关资源
    最近更新 更多