【问题标题】:Deduce first type from second non-type parameter of first type从第一类的第二个非类型参数推导出第一类
【发布时间】:2018-04-03 10:27:24
【问题描述】:

我有以下功能:

/// <summary>
/// Check whether next character in std::basic_istream is what expected. Skip it if so; otherwise, set fail flag.
/// </summary>
template <typename TCharType, TCharType char_>
std::basic_istream<TCharType>& skipIf(std::basic_istream<TCharType>& istream_)
{
    if ((istream_ >> std::ws).peek() == char_) {
        istream_.ignore();
    }
    else {
        istream_.setstate(std::ios_base::failbit);
    }
    return istream_;
}

它是这样工作的:

std::istringstream is {"some ; string"};
std::string temp;
if(is >> temp >> skipIf<char, ';'> >> temp) {
    // blah blah
}

有没有办法从给定的char_ 模板参数中推断出TCharType?如果我能写就更好了

  • skipIf&lt;';'&gt; -> 推导出为char
  • skipIf&lt;L';'&gt; -> 推导出为wchar_t
  • skipIf&lt;u';'&gt; -> 推导出为char16_t
  • skipIf&lt;U';'&gt; -> 推导出为char32_t

【问题讨论】:

  • C++17 是一个选项?
  • 是的,绝对的。

标签: c++ templates c++17 type-deduction


【解决方案1】:

您可以使用 C++17 的新 auto 非类型模板参数来做到这一点。稍微整理一下:

template <auto char_, typename TCharType = decltype(char_)>
std::basic_istream<TCharType>& skipIf(std::basic_istream<TCharType>& istream_)
{
    if ((istream_ >> std::ws).peek() == char_) {
        istream_.ignore();
    }
    else {
        istream_.setstate(std::ios_base::failbit);
    }
    return istream_;
}

你应该得到你所追求的,确切地说。您可以通过添加更多检查(作为 static_assert 或 SFINAE)来改进它,以确保 TCharType 确实是标准或扩展字符类型之一,但这是食谱解决方案。

【讨论】:

  • 可爱的解决方案!
  • 请注意,TCharType 可能会被推断出来,而不一定是decltype(char_)
  • @Jarod42 - 公平点。虽然如果这是一个问题,可以强制它成为一个非推断的上下文,或者完全放弃实用程序TCharType,但我只是不想对 OP 进行过多的重写。
【解决方案2】:

我会添加一个static_assert(is_same_v&lt;decltype(char_) , TCharType&gt;,"dont play"); 来使它好像第二个参数不存在一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-25
    • 2023-02-13
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    相关资源
    最近更新 更多