2017-10-04 11 views
0

clangとgccのテンプレートパラメータがどのように解決されるかには多少の違いがあるようです。あるいは、clangはatan2powバイナリ操作を考慮していないかもしれませんが、gccはバイナリ操作を考慮しません。引数atan2/powでstd :: transformsをコンパイルするのがclangで失敗しますが(gccで動作します)

以下のコードサンプルは、自分自身ではあまり意味がなく、最小限の方法で問題を再現していません:

#include <vector> 
#include <algorithm> 
#include <cmath> 

#define TRANSFORM_MACRO(op,func)           \ 
    template<class T>              \ 
    std::vector<T> &trans_##op(const std::vector<T> &a, const std::vector<T> &b, std::vector<T> &dst) { \ 
     std::transform(a.begin(), a.end(), b.begin(), dst.begin(), func); \ 
     return dst;               \ 
    }                  \ 
    template std::vector<float> &trans_##op(const std::vector<float>&, const std::vector<float>&, std::vector<float>&);  \ 
    template std::vector<double> &trans_##op(const std::vector<double>&, const std::vector<double>&, std::vector<double>&); 

TRANSFORM_MACRO(arctan2, ::atan2) 

int main() { 
    return 0; 
} 

をGCC(5.4 Ubuntuの、6.0 OSXシエラ)でこれをコンパイルするには、正常に動作します。打ち鳴らす(900.0.37)を使用すると、次のエラーが返されます。

/Users/alneuman/CLionProjects/temptest/main.cpp:15:1: error: no matching function for call to 'transform' 
TRANSFORM_MACRO(arctan2, atan2) 
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/Users/.../CLionProjects/temptest/main.cpp:9:7: note: expanded from macro 'TRANSFORM_MACRO' 
     std::transform(a.begin(), a.end(), b.begin(), dst.begin(), func);  \ 
     ^~~~~~~~~~~~~~ 
/Users/.../CLionProjects/temptest/main.cpp:15:1: note: in instantiation of function template specialization 'trans_arctan2<float>' requested here 
/Users/.../CLionProjects/temptest/main.cpp:12:34: note: expanded from macro 'TRANSFORM_MACRO' 
    template std::vector<float> &trans_##op(const std::vector<float>&, const std::vector<float>&, std::vector<float>&);  \ 
           ^
<scratch space>:22:1: note: expanded from here 
trans_arctan2 
^ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:1932:1: note: candidate template ignored: couldn't infer template argument '_BinaryOperation' 
transform(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2, 
^ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:1922:1: note: candidate function template not viable: requires 4 arguments, but 5 were provided 
transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op) 

問題は、GCCのみの仕様を必要としないため、一つの定義を持っているとatan2powの組み込みバージョンを使用していることのようです。 Clangは複数の定義を持つstd :: atan2/powに落ちているようです。 Clangには__builtin_atan2がありますが、コンパイラの出力を考慮して直接呼び出さなければならないため、これをstd::transformと一緒に使用することはできません。

+1

'std :: atan2;を使用すると、gccで問題が再現されます。 atan2がオーバーロードされているので、必要なオーバーロードを指定する必要があります。 –

+0

@MarcGlisse:これは私が正しい方向に向いていると思う。元のコードでは、 'std :: transform'はマクロの一部です(私はそれに応じて例を更新しました)。 'static_cast (func)'のようなテンプレートにfuncの関数ポインタをキャストすると、コードはclangでは動作しますが、gccでは動作しません。 GCCは、 'float(*)(float、float)'と入力すると 'double(double、double)'型の無効なstatic_castについて文句を言います。 GCCがatan2の浮動小数点バージョンを知らないように見えます。 – aleneum

+0

atan2を 'std :: atan2'に置き換えます.gccは浮動小数点バージョンを認識します。 (または 'atan2f'ですが、代わりに' 'を含める必要があります) –

答えて

0

@MarcGlisseのおかげで、私はClangとGCCのさまざまな動作の原因を突き止めました。 ::という表記法は、グローバル名前空間内の関数を探すように要求します。 GCCはatan2builtinであり、グローバル名前空間にはdoubleという署名がありますが、Clangは署名しません。 stdversion Clangは、機能がdoublefloatの署名を使用しています。したがって、std::atan2が使用されている場合、std::atan2は少なくとも3つのオーバーロード(float,doubleおよびlong double)を持つため、オーバーロードを使用する必要があるより詳しい情報がコンパイラに必要です。これは静的キャストで実現できます。 〜floatは静的にキャストできないため、GCCのビルド版を使用すると、明らかにキャストが失敗します。float

TRANSFORM_MACRO(arctan2, static_cast<T(*)(T, T)>(std::atan2))私はマクロのあいまいさを解決し、GCCとClangに同じバージョンのatan2を使用させました。

関連する問題