2017-03-27 1 views
0

大きなコードベースをclang(g ++およびintel C++でビルド)に移植しています。次のスニペットに似たコードがコンパイルされ、g++ 4.8 - 6.2で動作しますが、clang 3.8 and 3.9でコンパイルできません。もしことenable_ifを使用してベースクラスの戻り値型に特化する

#include <algorithm> 
#include <iostream> 
#include <type_traits> 

template <typename T> class Vector 
{ 
public: 
    Vector() : xyz{} {} 
    Vector(T const &x, T const &y, T const &z) : xyz{y, y, z} {} 
    Vector<T> min(Vector<T> const &v) { return Vector<T>(std::min(xyz[0], v.xyz[0]), std::min(xyz[1], v.xyz[1]), std::min(xyz[2], v.xyz[2])); } 
    T xyz[3]; 
}; 

class MinOpBase 
{ 
public: 
    template <class T> typename std::enable_if<!std::is_fundamental<T>::value>::type 
    operator()(Vector<T> &left, Vector<T> const &right) const { std::cout << "Don't call me!" << std::endl; } 
}; 

class MinOp : public MinOpBase 
{ 
public: 
    template <typename T> void operator()(T &left, T const &right) const 
    { left = std::min(left, right); } 

    // Support component-wise min on vectors of fundamental types 
    template <typename T> typename std::enable_if<std::is_fundamental<T>::value>::type 
    operator() (Vector<T> &left, Vector<T> const &right) const 
    { left.min(right); } 

    using MinOpBase::operator(); 
}; 

int main() 
{ 
    Vector<double> v1, v2; 
    Vector<Vector<double>> vv1, vv2; 
    MinOp m; 
    m(v1,v2); 
    m(vv1,vv2); 
} 

注:MinOpの2番目の呼び出しは、(AFAICT)基底クラスの専門(「!私を呼び出さないでください」)を取得する必要がありますが、打ち鳴らすは:: STDをインスタンス化する分バージョンを試み、失敗しました基本クラス(MinOpBase)がなく、「私に電話しない!」専門化は直接MinOpクラスclang works tooにあります。

これは、usingステートメントを使用して、ベースクラスの特殊化を有効にしていますか?

これはあまり価値のない機械のようなものです(もちろんこれはほとんど無意味な点で簡素化されていますが)。より良いアイデア?

+0

要件を記載してください。考慮すべき3つの条件がありますか? 2つの基本型、基本型の2つのベクトル、非基本型の2つのベクトル? –

+0

私にとって不運なバグに見えます。 – Jarod42

+0

@RichardHodges:私のコードではありませんが、私が理解している要件は次のとおりです。1.基本(フロート、ダブル)と非基本(複合、ベクトル、テンソルなど、浮動小数点数、 、など)。 2.複数の操作(最小、最大、割り当て、合計など)があります。すべての型ですべての操作が意味をなさないわけではありませんが、コンパイル時やリンク時ではなく実行時エラーで処理する必要があります。基本クラスはいくつかの操作で共有され、それらの操作をサポートしない多くの型をリストします。私はそれらの専門分野をそれぞれの派生語にコピーすることができます... –

答えて

0

同僚は私の質問は、私が打ち鳴らすの標準に従って「正しい」ことをやっているという結論が正しいと思い SFINAE not working on llvm/clang

の複製であることを指摘しました。ヨハネス・シャウブから - litbの答え:それは派生の メンバ関数テンプレートと同じ名前とパラメータを持っているので、C++ 11(継承された関数テンプレートの使用宣言の

7.3.3 P15は無視されますクラス)

他のコンパイラはおそらく「正しい」ものでなければなりませんが、これが標準の欠陥として報告されているかどうかはわかりません。

回避策には、すべての特殊化を基本クラスに入れたり、特殊化のいずれかの引数タイプの1つを変更することが含まれます。

関連する問題