2017-08-21 6 views
0

私はコンパイラとその自動テンプレート控除を使用する能力と戦っています。以下は、テンプレート自動控除の失敗で、コンパイルされません。テンプレート付き関数でオートタイプのlambdaを使用する - g ++ 5.4で自動テンプレート控除を使用する

template<typename Configuration, typename ConfigAlloc = std::allocator<Configuration>> 
std::vector<Configuration, ConfigAlloc> ResamplePath(
     const std::vector<Configuration, ConfigAlloc>& path, 
     const double resampled_state_distance, 
     const std::function<double(const Configuration&, const Configuration&)>& state_distance_fn, 
     const std::function<Configuration(const Configuration&, const Configuration&, const double)>& state_interpolation_fn) 
{ 
    ... 
} 

void foo() 
{ 
    std::vector<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d>> path; 
    ... 

    const auto interpolation_fn = [&] (
      const Eigen::Vector3d& prev, 
      const Eigen::Vector3d& curr, 
      const double ratio) 
    { 
     Eigen::Vector3d interpolated; 
     ... 
     return interpolated; 
    }; 

    auto resample_result = ResamplePath(path, ..., interpolation_fn); 
} 

私は

const std::function<Eigen::Vector3d(const Eigen::Vector3d&, const Eigen::Vector3d&, const double)> interpolation_fn = [&] (
      const Eigen::Vector3d& prev, 
      const Eigen::Vector3d& curr, 
      const double ratio) 
    { 
     Eigen::Vector3d interpolated; 
     ... 
     return interpolated; 
    }; 

またはI明示的なタイプ

auto resample_result = ResamplePath<Eigen::Vector3d, Eigen::aligned_allocator<Eigen::Vector3d>>(
       path, ..., interpolation_fn); 
を定義するための関数呼び出しを変更するにラムダ宣言のいずれかを変更した場合

すべてが問題なくコンパイルされます。

ラムダ型を明示的に定義しなくても自動デュレーション機能が動作しないようなものがありますか?

編集:正確なエラーをコンパイル

virtual_rubber_band.cpp: In member function ‘void smmap::VirtualRubberBand::resampleBand(bool)’: 
virtual_rubber_band.cpp:279:111: error: no matching function for call to ‘ResamplePath(EigenHelpers::VectorVector3d&, const double&, const smmap::VirtualRubberBand::resampleBand(bool)::<lambda(const Vector3d&, const Vector3d&)>&, const smmap::VirtualRubberBand::resampleBand(bool)::<lambda(const Vector3d&, const Vector3d&, double)>&)’ 
       band_, max_distance_between_rubber_band_points_, state_distance_fn, state_interpolation_fn); 
In file included from virtual_rubber_band.cpp:3:0: 
shortcut_smoothing.hpp:191:52: note: candidate: template<class Configuration, class ConfigAlloc> std::vector<_Tp, _Alloc> shortcut_smoothing::ResamplePath(const std::vector<_Tp, _Alloc>&, double, const std::function<double(const Datatype&, const Datatype&)>&, const std::function<Configuration(const Configuration&, const Configuration&, double)>&) 
inline std::vector<Configuration, ConfigAlloc> ResamplePath(
               ^
shortcut_smoothing.hpp:191:52: note: template argument deduction/substitution failed: 
virtual_rubber_band.cpp:279:111: note: ‘const smmap::VirtualRubberBand::resampleBand(bool)::<lambda(const Vector3d&, const Vector3d&)>’ is not derived from ‘const std::function<double(const Datatype&, const Datatype&)>’ 
       band_, max_distance_between_rubber_band_points_, state_distance_fn, state_interpolation_fn); 
+0

»次はコンパイルされません。テンプレートの自動控除のエラーが発生しました。«これはゲームのエラーなのでしょうか? –

+0

デバッグのヘルプ( "**なぜこのコードは動作しないのですか?**")は、質問自体に必要な動作、*特定の問題またはエラー*、* *を再現するのに必要な最短コード* **。 **明確な問題文**のない質問は他の読者には役に立たない。参照:[最小限で完全で検証可能なサンプルの作成方法](http://stackoverflow.com/help/mcve) –

+0

私は、最小限の、完全で、証明可能な例を作成しようとしましたが、これらの例は異なるライブラリにあるので作成するのが非常に難しいです。私が作成できた最小限の例は、およそ2000行のコードでした。私は要求通りに正確なコンパイルエラーを追加します。 – bitznarf

答えて

1

ラムダはSTD機能ではありません。

標準機能はタイプイレーサーです。それは、「署名付きの呼び出し」、コピー、および破棄(重要ではないもの)を除いてeceryを消去します。

型減算と型消去は逆の操作です。型消去型を控除するのはコード臭です。

template<typename Configuration, typename ConfigAlloc = std::allocator<Configuration>, 
    class Distance, class Interpolate> 
std::vector<Configuration, ConfigAlloc> ResamplePath(
    const std::vector<Configuration, ConfigAlloc>& path, 
    const double resampled_state_distance, 
    const Distance& state_distance_fn, 
    const Interpolate& state_interpolation_fn) 

ここで、タイプ消去の仕方を推測しようとしていません。タイプの消去を停止します。これは、コンパイラが型の消去よりもはるかに細かいインラインを見つけるため、実行時のパフォーマンスが向上する可能性があります。 block_deductionは、これらの引数を使用して推測しようとするから、コンパイラを防ぐ

template<typename Configuration, typename ConfigAlloc = std::allocator<Configuration>> 
std::vector<Configuration, ConfigAlloc> ResamplePath(
    const std::vector<Configuration, ConfigAlloc>& path, 
    const double resampled_state_distance, 
    block_deduction<const std::function<double(const Configuration&, const Configuration&)>&> state_distance_fn, 
    block_deduction<const std::function<Configuration(const Configuration&, const Configuration&, const double)>&> state_interpolation_fn) 

template<class T>struct tag_t{using type=T;}; 
template<class T>using block_deduction=typename tag_t<T>::type; 

あなたの本当の問題は、概念としてstd::functionを使用したいということはおそらくです - まだC++の一部ではありません - あなたは引数がその署名と互換性を持つようにしたいです。コンセプトはに到着する可能性があります。

+0

関数プロトタイプを変更できないと仮定すると、テンプレートパラメータを明示的に宣言することが最良の選択肢のように聞こえますか? 関数のプロトタイプを変更することができるかもしれませんが、それはこの時点でより長いプロセスを取るでしょう。 – bitznarf

+0

[この投稿](https:// stackoverflow。com/questions/16111285/pass-and-execution-anonymous-function-as-c11のパラメータ)は、人々がYakkの最初の解決策について詳細を知るのに役立ちます: – bitznarf

+0

@bitzラッパーを書く。いずれかのオプションを使用してオリジナルをラップすることができます。 – Yakk

関連する問題