2015-10-01 18 views
9

は、次のコードを考えてみましょう。ここでテンプレート引数の減算:どのコンパイラがここにありますか?

template<int N> 
class Vector 
{ 
}; 

#include <array> 

template<int N> 
void doWork(const Vector<N>&, const std::array<int,N>&) 
{ 
} 

int main() 
{ 
    std::array<int,3> arr; 
    Vector<3> vec; 
    doWork(vec,arr); 
} 

Vectorは、サードパーティのライブラリで定義されたクラスを表し、std::arraystd::size_tとしての要素数を取ることが知られています。 5.1 -

私が打ち鳴らす-3.6とg ++でこれをコンパイルしようとしました。

test.cpp: In function ‘int main()’: 
test.cpp:17:19: error: no matching function for call to ‘doWork(Vector<3>&, std::array<int, 3ul>&)’ 
    doWork(vec,arr); 
       ^
test.cpp:9:6: note: candidate: template<int N> void doWork(const Vector<N>&, const std::array<int, N>&) 
void doWork(const Vector<N>&, const std::array<int,N>&) 
    ^
test.cpp:9:6: note: template argument deduction/substitution failed: 
test.cpp:17:19: note: mismatched types ‘int’ and ‘long unsigned int’ 
    doWork(vec,arr); 
       ^
test.cpp:17:19: note: ‘std::array<int, 3ul>’ is not derived from ‘const std::array<int, N>’ 

私はdoWork()の2番目のパラメータでstd::size_tNのキャストをやったりdoWork<3>()を呼び出すことによって、この問題を回避することができますが、これは私を教育しません:G ++が次のエラーを与える一方でクランは、苦情なしで働いていました。

だから私はむしろ、最初に尋ねる:これは、コンパイラはここですか?私は実際にコードで何か間違っていますか(clangはあまりにも容認しやすいですか)、それとも本当に有効なC++ですか(g ++にはバグがあります)?

答えて

4

我々がドラフトC++ 11標準セクション14.8.2.5に行けば、私はそれが言う [temp.deduct.type]、gccがここに正確であると信じて:

If, in the declaration of a function template with a non-type template-parameter, the non-type templateparameter is used in an expression in the function parameter-list and, if the corresponding template-argument is deduced, the template-argument type shall match the type of the template-parameter exactly, except that a template-argument deduced from an array bound may be of any integral type.144 [ Example:

template<int i> class A { /* ... */ }; 
template<short s> void f(A<s>); 
void k1() { 
A<1> a; 
f(a); // error: deduction fails for conversion from int to short 
f<1>(a); // OK 
} 

[...]

と我々が変更された場合、私たちは見ることができますあなたのコードは次のようになります。

doWork<3>(vec,arr); 

gccはエラーを出力せず、clangも行いません。

我々はこの例を試す場合:

template<int N> 
void doWorkB(std::array<int,N>&) 
{ 
} 

//... 

doWorkB(arr); 

打ち鳴らすは現在、エラー(see it live)を生成します。我々は、パラメータの順序を入れ替える場合

note: candidate template ignored: substitution failure : deduced non-type template argument does not have the same type as the its corresponding template parameter ('unsigned long' vs 'int') 
void doWorkB(std::array<int,N>&) 
    ^

あなたのオリジナルのケースも打ち鳴らすに壊れる:

void doWork(const std::array<int,N>&, const Vector<N>&) 
関連する問題