C++17 の variant での同一型のエラーが typedef 越しだと分かりづらい2020年05月05日 12時45分32秒

C++17 から導入された variant 型。簡単にまとめると、オブジェクト指向の union 型。union は C の早い時期からある古い型だが、どの型が入っているのかは自ら処理しなければいけなかった。variant 型だと、言語側が現在の型の処理をしてくれる。また、union は型名とそれに対応する変数名で、値の参照の仕方を制御するが、variant 型には変数名が無い。

variant は型で指定するので、同じ型を複数回入れる意味は無い。

#include <variant>

int main()
{   
    std::variant< int, int > number;
    number = 3;
}
同じ型を渡すとエラーになる。
% c++ -std=c++17 variant_same_type.cpp
variant_same_type.cpp:6:12: error: no viable overloaded '='
    number = 3;
    ~~~~~~ ^ ~
/usr/include/c++/v1/variant:1215:12: note: candidate function not viable: no
      known conversion from 'int' to 'const std::__1::variant' for 1st
      argument
  variant& operator=(const variant&) = default;
           ^
/usr/include/c++/v1/variant:1216:12: note: candidate function not viable: no
      known conversion from 'int' to 'std::__1::variant' for 1st
      argument
  variant& operator=(variant&&) = default;
           ^
/usr/include/c++/v1/variant:1227:12: note: candidate template ignored:
      substitution failure [with _Arg = int, $1 = 0, _Tp = int]: no member named
      'value' in 'std::__1::__find_detail::__find_unambiguous_index_sfinae'
  variant& operator=(_Arg&& __arg) noexcept(
           ^
1 error generated.

ところがちょっと困ったことが起こった。typedef である。typedef へそれぞれの処理に都合の良い型に、名前を変換している事も多々ある。そして、int32 等のプラットフォーム非依存の、大きさ指定の型もコンパイル時に最終的な型の大きさが変わる。

#include <variant>

typedef int integer;

int main()
{   
    std::variant< int, integer > number;
    number = 3;
}
int 型と integer 型をしている。
% c++ -std=c++17 variant_typedef.cpp
variant_typedef.cpp:8:12: error: no viable overloaded '='
    number = 3;
    ~~~~~~ ^ ~
/usr/include/c++/v1/variant:1215:12: note: candidate function not viable: no
      known conversion from 'int' to 'const std::__1::variant' for 1st
      argument
  variant& operator=(const variant&) = default;
           ^
/usr/include/c++/v1/variant:1216:12: note: candidate function not viable: no
      known conversion from 'int' to 'std::__1::variant' for 1st
      argument
  variant& operator=(variant&&) = default;
           ^
/usr/include/c++/v1/variant:1227:12: note: candidate template ignored:
      substitution failure [with _Arg = int, $1 = 0, _Tp = int]: no member named
      'value' in 'std::__1::__find_detail::__find_unambiguous_index_sfinae'
  variant& operator=(_Arg&& __arg) noexcept(
           ^
1 error generated.
integer 型を int 型と報告してくれてはいるが、微妙に厄介。

次回

コメント

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://uyota.asablo.jp/blog/2020/05/05/9243118/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。