2016-04-05 13 views
6

GCC(5.3)& Clang(3.8)はtestの最初の行が悪いと主張しますが、2番目の行は問題ありません。 MSVC(2015.2)によれば、両方とも無効です。constexprテンプレート引数奇妙さ

template< typename N, typename T > 
void f(N n, T t) { std::get<n>(t); } 
void test() { 
    std::get< std::integral_constant< size_t, 0 >() >(std::make_tuple(123)); // not ok 
    f(std::integral_constant< size_t, 0 >(), std::make_tuple(123)); // ok for gcc, clang, but not msvc 
} 

正確には、標準によると違いはありますか?このコードは最初から正当なものですか?最初の行のための


打ち鳴らすエラー:

In file included from main.cpp:2: 
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:874:34: error: no matching function for call to '__get_helper2' 
    { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 
           ^~~~~~~~~~~~~~~~~~~~~~~ 
main.cpp:10:10: note: in instantiation of function template specialization 'std::get<std::integral_constant<unsigned long, 0>(), int>' requested here 
    std::get<std::integral_constant<size_t, 0>()>(std::make_tuple(123)); // not ok 
     ^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:856:5: note: candidate template ignored: could not match '_Tuple_impl' against 'tuple' 
    __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 
    ^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:861:5: note: candidate template ignored: could not match '_Tuple_impl' against 'tuple' 
    __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 
    ^
1 error generated. 

gccのエラー:

In file included from main.cpp:2:0: 
/usr/local/include/c++/5.3.0/tuple: In instantiation of 'constexpr _Tp&& std::get(std::tuple<_Elements ...>&&) [with _Tp = std::integral_constant<long unsigned int, 0ul>(); _Types = {int}]': 
main.cpp:10:75: required from here 
/usr/local/include/c++/5.3.0/tuple:874:57: error: no matching function for call to '__get_helper2(std::tuple<int>&)' 
    { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 
                 ^
/usr/local/include/c++/5.3.0/tuple:856:5: note: candidate: template<class _Head, long unsigned int __i, class ... _Tail> constexpr _Head& std::__get_helper2(std::_Tuple_impl<__i, _Head, _Tail ...>&) 
    __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 
    ^
/usr/local/include/c++/5.3.0/tuple:856:5: note: template argument deduction/substitution failed: 
/usr/local/include/c++/5.3.0/tuple:874:57: note: mismatched types 'std::integral_constant<long unsigned int, 0ul>()' and 'int' 
    { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 
                 ^
/usr/local/include/c++/5.3.0/tuple:874:57: note: 'std::tuple<int>' is not derived from 'std::_Tuple_impl<__i, std::integral_constant<long unsigned int, 0ul>(), _Tail ...>' 
/usr/local/include/c++/5.3.0/tuple:861:5: note: candidate: template<class _Head, long unsigned int __i, class ... _Tail> constexpr const _Head& std::__get_helper2(const std::_Tuple_impl<__i, _Head, _Tail ...>&) 
    __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 
    ^
/usr/local/include/c++/5.3.0/tuple:861:5: note: template argument deduction/substitution failed: 
/usr/local/include/c++/5.3.0/tuple:874:57: note: mismatched types 'std::integral_constant<long unsigned int, 0ul>()' and 'int' 
    { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 
                 ^
/usr/local/include/c++/5.3.0/tuple:874:57: note: 'std::tuple<int>' is not derived from 'const std::_Tuple_impl<__i, std::integral_constant<long unsigned int, 0ul>(), _Tail ...>' 
+0

あなたはどのようなエラーが発生しましたか教えてください。 –

+0

私はここにテキストの壁を掲示するのがあまり快適ではありませんが、ここにその要点があります。 MSVCの2行目: "'std :: get':一致するオーバーロードされた関数が見つかりませんでした。最初の行: 'std :: tuple'の内部を指している同様の行に沿ったあらゆる種類の通常の巨大なジャンボ。 – vpozdyayev

+1

@vpozdyayevエラーは多くの助けになります。問題の内容を理解するためのエラーメッセージです。それはただのジャンボではない。 – Barry

答えて

6

TL; DRは、私は両方のケースでgccと打ち鳴らすの行動が正しいと思います。


2つの呼び出しの間に微妙な違いがあります。私はただ説明するためにエイリアスを追加してみましょう:

using Zero = std::integral_constant<size_t, 0>; 
auto tuple = std::make_tuple(123); 

あなたが書いた:

std::get<Zero()>(tuple); 

Zero()タイプです。 Zeroを返すnullary関数です。このように、std::getのバージョンはstd::get<T>()となります。 tupleにタイプがZero()の要素がないため、これはエラーです。あなたが書く一方

、:

Zero n; 
std::get<n>(tuple); 

nはタイプではありません - それは今までの値です。 std::integral_constantにはconstexpr operator size_t()が含まれているため、その番号が使用され、std::get<I>()と呼ばれることになります。

同じ単にもブレース初期化を使用することによって達成することができる:

std::get<Zero{}>(tuple); 

Zero{}は間違いタイプではないからです。

+1

ああ、良いol '最も厄介な構文解析:) ...私はそれを完全に忘れている近年では、C + +はとても便利になってきています。 – vpozdyayev

+0

実際には 'std :: get (タプル);'行はClangでは動作しますが、GCCでは動作しません(「nの値は定数式では使用できません」/「n」は宣言されていません'constexpr' ")。それはGCCのバグでしょうか? – vpozdyayev

+0

@vpozdyayev実際に有効なコードではなく、実際のケースを要約したものです。 – Barry

関連する問題