1

boost::optionalライブラリ コードによって生成された例外をキャッチし、それらをs (または)でラップしたいと考えていますstd::experimental::optional。私のコードは些​​細なケースでは機能しますが、オーバーロードされた関数を呼び出すときに正しい型を推測するのは困難です。テストケースをこれに減らしました:

// Compile with: clang++ -std=c++14 -stdlib=libc++ -Wall -Wshadow -Wextra -o except_to_optional except_to_optional.cpp
#include <iostream>
#include <boost/optional.hpp>

template<typename Func, typename... Args>
auto try_call(Func f, Args&&... args) noexcept -> boost::optional<std::decay_t<decltype(f(std::forward<Args>(args)...))>>
{
  using RT = std::decay_t<decltype(f(std::forward<Args>(args)...))>;
  try {
    return boost::make_optional<RT>(f(std::forward<Args>(args)...));
  } catch(...) {
    return boost::none;
  }
}

int func1(char * ptr)
{
  if (!ptr)
    throw 14;

  return strlen(ptr);
}

int func1(char * ptr, size_t len)
{
  if (!ptr)
    throw 14;

  const size_t calc_len = strlen(ptr);
  return calc_len < len ? calc_len : len;
}

int main(int argc, char **argv)
{
  char *omg = "omg";

#if 1
  // This is the desired syntax, but it fails
  auto val = try_call(func1, omg);
#else
  // This works, but its ugly
  int (*f)(char *) = func1;
  auto val = try_call(f, omg);
#endif

  if (val)
    std::cout << omg << " has a length of " << *val << "\n";
  else
    std::cout << "Something went wrong...\n";

  return 0;
}

「壊れた」例をコンパイルしようとすると、次の出力が得られます。

except_to_optional.cpp:50:14: error: no matching function for call to 'try_call'
  auto val = try_call(func1, omg);
             ^~~~~~~~
except_to_optional.cpp:17:6: note: candidate template ignored: couldn't infer template argument 'Func'
auto try_call(Func f, Args&&... args) noexcept -> boost::optional<std::decay_t<decltype(f(std::forward<Args>(args)...))>>
     ^

正しい型の関数ポインタを作成することで問題を回避できますが、これは理想的ではありません。私の問題の解決策はありますか、それとも醜い関数ポインタのハックに悩まされていますか?

乾杯、ライアン

4

1 に答える 1

2

func1最初のケースでは、渡したいの 2 つの異なるバージョンがあります。コンパイラはfunc1、テンプレートをインスタンス化するために必要な型を判断できないため、テンプレートの「内部を調べて」「1 つのパラメーター」バージョンが正しいものであることを確認するまでには至りません。

それが、コンパイラのエラー メッセージが伝えていることです。

2 番目のケースでは、 の 1 つのオーバーロードを選択func1して に渡しtry_callます。あいまいさがないため、コンパイラはテンプレートに適用する署名を判断できます。

于 2016-10-18T02:19:45.050 に答える