templateの明示的特殊化・intXXX_t型 について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
m3908714035
記事: 12
登録日時: 3ヶ月前

templateの明示的特殊化・intXXX_t型 について

#1

投稿記事 by m3908714035 » 3ヶ月前

以前別トピック「scanf を簡略化したい」で質問させていただいた者です。コードを書いている中でscanfの簡略とは異なった点で疑問が生じましたので、新しくトピックを立てさせていただきます。

code:

コード:

struct in
{
	template<typename typ> in& operator>>(typ& val) { std::cin >> val; return *this; }
	template<> in& operator>>(char& val) { std::scanf(" %c", &val); return *this; }
	template<> in& operator>>(std::int_fast8_t& val) { std::scanf("%hd", &val); return *this; }
	template<> in& operator>>(std::uint_fast8_t& val) { std::scanf("%hu", &val); return *this; }
	template<> in& operator>>(std::int_fast16_t& val) { std::scanf("%d", &val); return *this; }
	template<> in& operator>>(std::uint_fast16_t& val) { std::scanf("%u", &val); return *this; }
	template<> in& operator>>(std::int_fast32_t& val) { std::scanf("%ld", &val); return *this; }
	template<> in& operator>>(std::uint_fast32_t& val) { std::scanf("%lu", &val); return *this; }
	template<> in& operator>>(std::int_fast64_t& val) { std::scanf("%lld", &val); return *this; }
	template<> in& operator>>(std::uint_fast64_t& val) { std::scanf("%llu", &val); return *this; }
	template<> in& operator>>(float& val) { std::scanf("%f", &val); return *this; }
	template<> in& operator>>(double& val) { std::scanf("%lf", &val); return *this; }
};

struct out
{
    template<typename typ> template<>out& operator<<(typ& val) { std::cout << val; return *this; }
	template<> out& operator<<(char& val) { std::printf("%c", val); return *this; }
	template<> out& operator<<(std::int_fast8_t& val) { std::printf("%hd", val); return *this; }
	template<> out& operator<<(std::uint_fast8_t& val) { std::printf("%hu", val); return *this; }
	template<> out& operator<<(std::int_fast16_t& val) { std::printf("%d", val); return *this; }
	template<> out& operator<<(std::uint_fast16_t& val) { std::printf("%u", val); return *this; }
	template<> out& operator<<(std::int_fast32_t& val) { std::printf("%ld", val); return *this; }
	template<> out& operator<<(std::uint_fast32_t& val) { std::printf("%lu", val); return *this; }
	template<> out& operator<<(std::int_fast64_t& val) { std::printf("%lld", val); return *this; }
	template<> out& operator<<(std::uint_fast64_t& val) { std::printf("%llu", val); return *this; }
	template<> out& operator<<(float& val) { std::printf("%f", val); return *this; }
	template<> out& operator<<(double& val) { std::printf("%lf", val); return *this; }
};
前回のコードにprintfも加えて、scanfとprintfをどのクラスに対してもinとoutで入出力できるようにしたものです。実際に書いたコードはマクロを使用して簡略化させてあります。また、int等のクラスが実行環境によって変わってしまうことがあるということを知ったため、cstdintを用いてintXXX_tを形を使いました。このinとoutを含んだコードを実行すると以下のエラーが発生しました。

error: (https://wandbox.org/ C++ gcc HEAD 9.0.0 20181227 (experimental))

コード:

prog.cc:9:11: error: explicit specialization in non-namespace scope 'struct in'
    9 |  template<> in& operator>>(char& val) { std::scanf(" %c", &val); return *this; }
      |           ^
prog.cc:10:11: error: explicit specialization in non-namespace scope 'struct in'
   10 |  template<> in& operator>>(std::int_fast8_t& val) { std::scanf("%hd", &val); return *this; }
      |           ^
prog.cc:11:11: error: explicit specialization in non-namespace scope 'struct in'
   11 |  template<> in& operator>>(std::uint_fast8_t& val) { std::scanf("%hu", &val); return *this; }
      |           ^
prog.cc:12:11: error: explicit specialization in non-namespace scope 'struct in'
   12 |  template<> in& operator>>(std::int_fast16_t& val) { std::scanf("%d", &val); return *this; }
      |           ^
prog.cc:13:11: error: explicit specialization in non-namespace scope 'struct in'
   13 |  template<> in& operator>>(std::uint_fast16_t& val) { std::scanf("%u", &val); return *this; }
      |           ^
prog.cc:14:11: error: explicit specialization in non-namespace scope 'struct in'
   14 |  template<> in& operator>>(std::int_fast32_t& val) { std::scanf("%ld", &val); return *this; }
      |           ^
prog.cc:14:17: error: 'in& in::operator>>(int_fast32_t&)' cannot be overloaded with 'in& in::operator>>(int_fast16_t&)'
   14 |  template<> in& operator>>(std::int_fast32_t& val) { std::scanf("%ld", &val); return *this; }
      |                 ^~~~~~~~
prog.cc:12:17: note: previous declaration 'in& in::operator>>(int_fast16_t&)'
   12 |  template<> in& operator>>(std::int_fast16_t& val) { std::scanf("%d", &val); return *this; }
      |                 ^~~~~~~~
prog.cc:15:11: error: explicit specialization in non-namespace scope 'struct in'
   15 |  template<> in& operator>>(std::uint_fast32_t& val) { std::scanf("%lu", &val); return *this; }
      |           ^
prog.cc:15:17: error: 'in& in::operator>>(uint_fast32_t&)' cannot be overloaded with 'in& in::operator>>(uint_fast16_t&)'
   15 |  template<> in& operator>>(std::uint_fast32_t& val) { std::scanf("%lu", &val); return *this; }
      |                 ^~~~~~~~
prog.cc:13:17: note: previous declaration 'in& in::operator>>(uint_fast16_t&)'
   13 |  template<> in& operator>>(std::uint_fast16_t& val) { std::scanf("%u", &val); return *this; }
      |                 ^~~~~~~~
prog.cc:16:11: error: explicit specialization in non-namespace scope 'struct in'
   16 |  template<> in& operator>>(std::int_fast64_t& val) { std::scanf("%lld", &val); return *this; }
      |           ^
prog.cc:16:17: error: 'in& in::operator>>(int_fast64_t&)' cannot be overloaded with 'in& in::operator>>(int_fast16_t&)'
   16 |  template<> in& operator>>(std::int_fast64_t& val) { std::scanf("%lld", &val); return *this; }
      |                 ^~~~~~~~
prog.cc:12:17: note: previous declaration 'in& in::operator>>(int_fast16_t&)'
   12 |  template<> in& operator>>(std::int_fast16_t& val) { std::scanf("%d", &val); return *this; }
      |                 ^~~~~~~~
prog.cc:17:11: error: explicit specialization in non-namespace scope 'struct in'
   17 |  template<> in& operator>>(std::uint_fast64_t& val) { std::scanf("%llu", &val); return *this; }
      |           ^
prog.cc:17:17: error: 'in& in::operator>>(uint_fast64_t&)' cannot be overloaded with 'in& in::operator>>(uint_fast16_t&)'
   17 |  template<> in& operator>>(std::uint_fast64_t& val) { std::scanf("%llu", &val); return *this; }
      |                 ^~~~~~~~
prog.cc:13:17: note: previous declaration 'in& in::operator>>(uint_fast16_t&)'
   13 |  template<> in& operator>>(std::uint_fast16_t& val) { std::scanf("%u", &val); return *this; }
      |                 ^~~~~~~~
prog.cc:18:11: error: explicit specialization in non-namespace scope 'struct in'
   18 |  template<> in& operator>>(float& val) { std::scanf("%f", &val); return *this; }
      |           ^
prog.cc:19:11: error: explicit specialization in non-namespace scope 'struct in'
   19 |  template<> in& operator>>(double& val) { std::scanf("%lf", &val); return *this; }
      |           ^
prog.cc: In member function 'in& in::operator>>(int_fast8_t&)':
prog.cc:10:67: warning: format '%hd' expects argument of type 'short int*', but argument 2 has type 'int_fast8_t*' {aka 'signed char*'} [-Wformat=]
   10 |  template<> in& operator>>(std::int_fast8_t& val) { std::scanf("%hd", &val); return *this; }
      |                                                                 ~~^   ~~~~
      |                                                                   |   |
      |                                                                   |   int_fast8_t* {aka signed char*}
      |                                                                   short int*
      |                                                                 %hhd
prog.cc: In member function 'in& in::operator>>(uint_fast8_t&)':
prog.cc:11:68: warning: format '%hu' expects argument of type 'short unsigned int*', but argument 2 has type 'uint_fast8_t*' {aka 'unsigned char*'} [-Wformat=]
   11 |  template<> in& operator>>(std::uint_fast8_t& val) { std::scanf("%hu", &val); return *this; }
      |                                                                  ~~^   ~~~~
      |                                                                    |   |
      |                                                                    |   uint_fast8_t* {aka unsigned char*}
      |                                                                    short unsigned int*
      |                                                                  %hhu
prog.cc: In member function 'in& in::operator>>(int_fast16_t&)':
prog.cc:12:67: warning: format '%d' expects argument of type 'int*', but argument 2 has type 'int_fast16_t*' {aka 'long int*'} [-Wformat=]
   12 |  template<> in& operator>>(std::int_fast16_t& val) { std::scanf("%d", &val); return *this; }
      |                                                                  ~^   ~~~~
      |                                                                   |   |
      |                                                                   |   int_fast16_t* {aka long int*}
      |                                                                   int*
      |                                                                  %ld
prog.cc: In member function 'in& in::operator>>(uint_fast16_t&)':
prog.cc:13:68: warning: format '%u' expects argument of type 'unsigned int*', but argument 2 has type 'uint_fast16_t*' {aka 'long unsigned int*'} [-Wformat=]
   13 |  template<> in& operator>>(std::uint_fast16_t& val) { std::scanf("%u", &val); return *this; }
      |                                                                   ~^   ~~~~
      |                                                                    |   |
      |                                                                    |   uint_fast16_t* {aka long unsigned int*}
      |                                                                    unsigned int*
      |                                                                   %lu
prog.cc: In member function 'in& in::operator>>(int_fast64_t&)':
prog.cc:16:69: warning: format '%lld' expects argument of type 'long long int*', but argument 2 has type 'int_fast64_t*' {aka 'long int*'} [-Wformat=]
   16 |  template<> in& operator>>(std::int_fast64_t& val) { std::scanf("%lld", &val); return *this; }
      |                                                                  ~~~^   ~~~~
      |                                                                     |   |
      |                                                                     |   int_fast64_t* {aka long int*}
      |                                                                     long long int*
      |                                                                  %ld
prog.cc: In member function 'in& in::operator>>(uint_fast64_t&)':
prog.cc:17:70: warning: format '%llu' expects argument of type 'long long unsigned int*', but argument 2 has type 'uint_fast64_t*' {aka 'long unsigned int*'} [-Wformat=]
   17 |  template<> in& operator>>(std::uint_fast64_t& val) { std::scanf("%llu", &val); return *this; }
      |                                                                   ~~~^   ~~~~
      |                                                                      |   |
      |                                                                      |   uint_fast64_t* {aka long unsigned int*}
      |                                                                      long long unsigned int*
      |                                                                   %lu
prog.cc: At global scope:
prog.cc:24:37: error: invalid explicit specialization before '>' token
   24 |     template<typename typ> template<> out& operator<<(typ& val) { std::cout << val; return *this; }
      |                                     ^
prog.cc:24:37: error: explicit specialization in non-namespace scope 'struct out'
prog.cc:24:42: error: too many template-parameter-lists
   24 |     template<typename typ> template<> out& operator<<(typ& val) { std::cout << val; return *this; }
      |                                          ^
prog.cc:25:11: error: explicit specialization in non-namespace scope 'struct out'
   25 |  template<> out& operator<<(char& val) { std::printf("%c", val); return *this; }
      |           ^
prog.cc:26:11: error: explicit specialization in non-namespace scope 'struct out'
   26 |  template<> out& operator<<(std::int_fast8_t& val) { std::printf("%hd", val); return *this; }
      |           ^
prog.cc:27:11: error: explicit specialization in non-namespace scope 'struct out'
   27 |  template<> out& operator<<(std::uint_fast8_t& val) { std::printf("%hu", val); return *this; }
      |           ^
prog.cc:28:11: error: explicit specialization in non-namespace scope 'struct out'
   28 |  template<> out& operator<<(std::int_fast16_t& val) { std::printf("%d", val); return *this; }
      |           ^
prog.cc:29:11: error: explicit specialization in non-namespace scope 'struct out'
   29 |  template<> out& operator<<(std::uint_fast16_t& val) { std::printf("%u", val); return *this; }
      |           ^
prog.cc:30:11: error: explicit specialization in non-namespace scope 'struct out'
   30 |  template<> out& operator<<(std::int_fast32_t& val) { std::printf("%ld", val); return *this; }
      |           ^
prog.cc:30:18: error: 'out& out::operator<<(int_fast32_t&)' cannot be overloaded with 'out& out::operator<<(int_fast16_t&)'
   30 |  template<> out& operator<<(std::int_fast32_t& val) { std::printf("%ld", val); return *this; }
      |                  ^~~~~~~~
prog.cc:28:18: note: previous declaration 'out& out::operator<<(int_fast16_t&)'
   28 |  template<> out& operator<<(std::int_fast16_t& val) { std::printf("%d", val); return *this; }
      |                  ^~~~~~~~
prog.cc:31:11: error: explicit specialization in non-namespace scope 'struct out'
   31 |  template<> out& operator<<(std::uint_fast32_t& val) { std::printf("%lu", val); return *this; }
      |           ^
prog.cc:31:18: error: 'out& out::operator<<(uint_fast32_t&)' cannot be overloaded with 'out& out::operator<<(uint_fast16_t&)'
   31 |  template<> out& operator<<(std::uint_fast32_t& val) { std::printf("%lu", val); return *this; }
      |                  ^~~~~~~~
prog.cc:29:18: note: previous declaration 'out& out::operator<<(uint_fast16_t&)'
   29 |  template<> out& operator<<(std::uint_fast16_t& val) { std::printf("%u", val); return *this; }
      |                  ^~~~~~~~
prog.cc:32:11: error: explicit specialization in non-namespace scope 'struct out'
   32 |  template<> out& operator<<(std::int_fast64_t& val) { std::printf("%lld", val); return *this; }
      |           ^
prog.cc:32:18: error: 'out& out::operator<<(int_fast64_t&)' cannot be overloaded with 'out& out::operator<<(int_fast16_t&)'
   32 |  template<> out& operator<<(std::int_fast64_t& val) { std::printf("%lld", val); return *this; }
      |                  ^~~~~~~~
prog.cc:28:18: note: previous declaration 'out& out::operator<<(int_fast16_t&)'
   28 |  template<> out& operator<<(std::int_fast16_t& val) { std::printf("%d", val); return *this; }
      |                  ^~~~~~~~
prog.cc:33:11: error: explicit specialization in non-namespace scope 'struct out'
   33 |  template<> out& operator<<(std::uint_fast64_t& val) { std::printf("%llu", val); return *this; }
      |           ^
prog.cc:33:18: error: 'out& out::operator<<(uint_fast64_t&)' cannot be overloaded with 'out& out::operator<<(uint_fast16_t&)'
   33 |  template<> out& operator<<(std::uint_fast64_t& val) { std::printf("%llu", val); return *this; }
      |                  ^~~~~~~~
prog.cc:29:18: note: previous declaration 'out& out::operator<<(uint_fast16_t&)'
   29 |  template<> out& operator<<(std::uint_fast16_t& val) { std::printf("%u", val); return *this; }
      |                  ^~~~~~~~
prog.cc:34:11: error: explicit specialization in non-namespace scope 'struct out'
   34 |  template<> out& operator<<(float& val) { std::printf("%f", val); return *this; }
      |           ^
prog.cc:35:11: error: explicit specialization in non-namespace scope 'struct out'
   35 |  template<> out& operator<<(double& val) { std::printf("%lf", val); return *this; }
      |           ^
prog.cc: In member function 'out& out::operator<<(int_fast16_t&)':
prog.cc:28:69: warning: format '%d' expects argument of type 'int', but argument 2 has type 'int_fast16_t' {aka 'long int'} [-Wformat=]
   28 |  template<> out& operator<<(std::int_fast16_t& val) { std::printf("%d", val); return *this; }
      |                                                                    ~^   ~~~
      |                                                                     |   |
      |                                                                     int int_fast16_t {aka long int}
      |                                                                    %ld
prog.cc: In member function 'out& out::operator<<(uint_fast16_t&)':
prog.cc:29:70: warning: format '%u' expects argument of type 'unsigned int', but argument 2 has type 'uint_fast16_t' {aka 'long unsigned int'} [-Wformat=]
   29 |  template<> out& operator<<(std::uint_fast16_t& val) { std::printf("%u", val); return *this; }
      |                                                                     ~^   ~~~
      |                                                                      |   |
      |                                                                      |   uint_fast16_t {aka long unsigned int}
      |                                                                      unsigned int
      |                                                                     %lu
prog.cc: In member function 'out& out::operator<<(int_fast64_t&)':
prog.cc:32:71: warning: format '%lld' expects argument of type 'long long int', but argument 2 has type 'int_fast64_t' {aka 'long int'} [-Wformat=]
   32 |  template<> out& operator<<(std::int_fast64_t& val) { std::printf("%lld", val); return *this; }
      |                                                                    ~~~^   ~~~
      |                                                                       |   |
      |                                                                       |   int_fast64_t {aka long int}
      |                                                                       long long int
      |                                                                    %ld
prog.cc: In member function 'out& out::operator<<(uint_fast64_t&)':
prog.cc:33:72: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 2 has type 'uint_fast64_t' {aka 'long unsigned int'} [-Wformat=]
   33 |  template<> out& operator<<(std::uint_fast64_t& val) { std::printf("%llu", val); return *this; }
      |                                                                     ~~~^   ~~~
      |                                                                        |   |
      |                                                                        |   uint_fast64_t {aka long unsigned int}
      |                                                                        long long unsigned int
      |                                                                     %lu
今回の疑問点は4つです。
①explicit specializationとは?
②どうしてクラス同士で衝突が起こり同時にオペレータを定義できないのか。
③-1 ex) int_fast64_tはcstdintでtypedef long long int_fast64_t;と定義されているのにエラーではint_fast64_t {aka long int}と型が異なっているのは何故か。
③-2 そもそもcstdintで以下のように3つとも同じように定義されているのに「_fastタイプが各プラットフォームがハードウェアに「便利」なタイプを指定できるタイプエイリアス」となるのはどうしてか。

cstdint(一部抜粋)

コード:

typedef int int32_t;
typedef int int_least32_t;
typedef int int_fast32_t;
自身でも様々なサイトを参考にエラーを訂正しているつもりですが、プログラミング経験がまだまだ浅く上手くいきません。もしかするとしょうもない部分を質問しているのかもしれませんが、改善策と共にご教示いただけると幸いです。

m3908714035
記事: 12
登録日時: 3ヶ月前

Re: templateの明示的特殊化・intXXX_t型 について

#2

投稿記事 by m3908714035 » 3ヶ月前

余談ではありますが、main部分にint_fast16_t i; in() >> i; out() << i << "\n";とすると、
error:

コード:

prog.cc: In function 'int main()':
prog.cc:39:43: error: ambiguous overload for 'operator<<' (operand types are 'out' and 'const char [2]')
   39 |     int_fast16_t i; in() >> i; out() << i << "\n";
      |                                ~~~~~~~~~~ ^~ ~~~~
      |                                      |       |
      |                                      out     const char [2]
prog.cc:25:18: note: candidate: 'out& out::operator<<(char&)' <near match>
   25 |  template<> out& operator<<(char& val) { std::printf("%c", val); return *this; }
      |                  ^~~~~~~~
prog.cc:25:18: note:   conversion of argument 1 would be ill-formed:
prog.cc:39:46: error: invalid conversion from 'const char*' to 'char' [-fpermissive]
   39 |     int_fast16_t i; in() >> i; out() << i << "\n";
      |                                              ^~~~
      |                                              |
      |                                              const char*
prog.cc:39:46: error: cannot bind rvalue '(char)((const char*)"\012")' to 'char&'
prog.cc:26:18: note: candidate: 'out& out::operator<<(int_fast8_t&)' <near match>
   26 |  template<> out& operator<<(std::int_fast8_t& val) { std::printf("%hd", val); return *this; }
      |                  ^~~~~~~~
prog.cc:26:18: note:   conversion of argument 1 would be ill-formed:
prog.cc:39:46: error: invalid conversion from 'const char*' to 'int_fast8_t' {aka 'signed char'} [-fpermissive]
   39 |     int_fast16_t i; in() >> i; out() << i << "\n";
      |                                              ^~~~
      |                                              |
      |                                              const char*
prog.cc:39:46: error: cannot bind rvalue '(int_fast8_t)((const char*)"\012")' to 'int_fast8_t&' {aka 'signed char&'}
prog.cc:27:18: note: candidate: 'out& out::operator<<(uint_fast8_t&)' <near match>
   27 |  template<> out& operator<<(std::uint_fast8_t& val) { std::printf("%hu", val); return *this; }
      |                  ^~~~~~~~
prog.cc:27:18: note:   conversion of argument 1 would be ill-formed:
prog.cc:39:46: error: invalid conversion from 'const char*' to 'uint_fast8_t' {aka 'unsigned char'} [-fpermissive]
   39 |     int_fast16_t i; in() >> i; out() << i << "\n";
      |                                              ^~~~
      |                                              |
      |                                              const char*
prog.cc:39:46: error: cannot bind rvalue '(uint_fast8_t)((const char*)"\012")' to 'uint_fast8_t&' {aka 'unsigned char&'}
prog.cc:28:18: note: candidate: 'out& out::operator<<(int_fast16_t&)' <near match>
   28 |  template<> out& operator<<(std::int_fast16_t& val) { std::printf("%d", val); return *this; }
      |                  ^~~~~~~~
prog.cc:28:18: note:   conversion of argument 1 would be ill-formed:
prog.cc:39:46: error: invalid conversion from 'const char*' to 'int_fast16_t' {aka 'long int'} [-fpermissive]
   39 |     int_fast16_t i; in() >> i; out() << i << "\n";
      |                                              ^~~~
      |                                              |
      |                                              const char*
prog.cc:39:46: error: cannot bind rvalue '(int_fast16_t)((const char*)"\012")' to 'int_fast16_t&' {aka 'long int&'}
prog.cc:29:18: note: candidate: 'out& out::operator<<(uint_fast16_t&)' <near match>
   29 |  template<> out& operator<<(std::uint_fast16_t& val) { std::printf("%u", val); return *this; }
      |                  ^~~~~~~~
prog.cc:29:18: note:   conversion of argument 1 would be ill-formed:
prog.cc:39:46: error: invalid conversion from 'const char*' to 'uint_fast16_t' {aka 'long unsigned int'} [-fpermissive]
   39 |     int_fast16_t i; in() >> i; out() << i << "\n";
      |                                              ^~~~
      |                                              |
      |                                              const char*
prog.cc:39:46: error: cannot bind rvalue '(uint_fast16_t)((const char*)"\012")' to 'uint_fast16_t&' {aka 'long unsigned int&'}
となりました。自分の中ではこーどのtemplate<typename typ>の挙動を取ってくれると思っていたのですが、何が問題だったのでしょうか。

かずま

Re: templateの明示的特殊化・intXXX_t型 について

#3

投稿記事 by かずま » 3ヶ月前

m3908714035 さんが書きました:
3ヶ月前
①explicit specializationとは?
template の「明示的な特殊化」で、
template<> in& operator>>(char& val) を C++11 からは、
template<char> in& operator>>(char& val) と書かなくてはいけなく
なったようです。
あるいは、template<> を削除し、単にオーバーロード関数として
in& operator>>(char& val) と書いてもよいのではないでしょうか。
m3908714035 さんが書きました:
3ヶ月前
②どうしてクラス同士で衝突が起こり同時にオペレータを定義できないのか。
③-1 ex) int_fast64_tはcstdintでtypedef long long int_fast64_t;と定義されているのにエラーではint_fast64_t {aka long int}と型が異なっているのは何故か。
③-2 そもそもcstdintで以下のように3つとも同じように定義されているのに「_fastタイプが各プラットフォームがハードウェアに「便利」なタイプを指定できるタイプエイリアス」となるのはどうしてか。
int_fast16_t, int_fast32_t, int_fast64_t が全部 long だから。
64ビット環境の g++ では、long も long long も 8バイトです。
m3908714035 さんが書きました:
3ヶ月前
改善策と共にご教示いただけると幸いです。
cstdint で typedef されている型名でなく、char, short, int のような基本型で
書いたほうが良いのではないでしょうか?

m3908714035
記事: 12
登録日時: 3ヶ月前

Re: templateの明示的特殊化・intXXX_t型 について

#4

投稿記事 by m3908714035 » 3ヶ月前

回答ありがとうございます。nt型等は環境のビット数に依存すると聞き、intXXX_t型の使用を考えました。まあ、intXXX_t型も少なくともXXXビットの整数を保証しているだけなのですが。
ただ、そこまで環境によって困ったこともありませんし、基本形の方が良いんですかね…。
その点は今一度考えてみます。

かずま

Re: templateの明示的特殊化・intXXX_t型 について

#5

投稿記事 by かずま » 3ヶ月前

m3908714035 さんが書きました:
3ヶ月前
余談ではありますが、main部分にint_fast16_t i; in() >> i; out() << i << "\n";とすると、
error:
struct out の
template<typename typ> template<>out& operator<<(typ& val) の
tempalte<> を削除すればよいのでは?

naohiro19
記事: 256
登録日時: 8年前
住所: 愛知県

Re: templateの明示的特殊化・intXXX_t型 について

#6

投稿記事 by naohiro19 » 3ヶ月前

Visual Studio 2017のC++17 (/std:c++17)モードでコンパイルすると

コード:

'in &in::operator >><int_fast16_t>(int_fast16_t &)': メンバー関数は、既に定義または宣言されています。
note: 'in::operator >>' の宣言を確認してください
明示的な特殊化 'in &in::operator >>(int_fast32_t &)' は関数テンプレートの特殊化ではありません
'in &in::operator >><uint_fast16_t>(uint_fast16_t &)': メンバー関数は、既に定義または宣言されています。
'in::operator >>' の宣言を確認してください
明示的な特殊化 'in &in::operator >>(uint_fast32_t &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(typ &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(char &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(int_fast8_t &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(uint_fast8_t &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(int_fast16_t &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(uint_fast16_t &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(int_fast32_t &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(uint_fast32_t &)' は関数テンプレートの特殊化ではありません
 明示的な特殊化 'out &out::operator <<(int_fast64_t &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(uint_fast64_t &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(float &)' は関数テンプレートの特殊化ではありません
明示的な特殊化 'out &out::operator <<(double &)' は関数テンプレートの特殊化ではありません
と怒られます。

アバター
tk-xleader
記事: 153
登録日時: 8年前
連絡を取る:

Re: templateの明示的特殊化・intXXX_t型 について

#7

投稿記事 by tk-xleader » 3ヶ月前

①explicit specializationとは?
メンバー演算子関数テンプレートの明示的特殊化の書き方はこうです。

コード:

#include <iostream>

namespace my{
    struct X{
        template<typename T>
        void operator>>(T)const{
            std::cout<<"primary template."<<std::endl;
        }
        template<> void operator>> <int>(int t)const{
            std::cout<<"specialized for int:" << t <<std::endl;
        }
    };
}

int main()
{
    my::X x;
    x >> "";
    x >> 0;
}
②どうしてクラス同士で衝突が起こり同時にオペレータを定義できないのか。
int_fastXXX_tは、それぞれ異なる型であることが保証されていないからです。たとえば、int_fast16_tとint_fast32_tは、同じ整数型の別名となることがありえます。そういう環境だと、両者に対する明示的特殊化を同時に実装した場合、同じ型に対する複数の明示的特殊化を実装してしまうことになるので、重複が生じてエラーになるのです。
③-1 ex) int_fast64_tはcstdintでtypedef long long int_fast64_t;と定義されているのにエラーではint_fast64_t {aka long int}と型が異なっているのは何故か。
③-2 そもそもcstdintで以下のように3つとも同じように定義されているのに「_fastタイプが各プラットフォームがハードウェアに「便利」なタイプを指定できるタイプエイリアス」となるのはどうしてか。
int_fastXXX_tは、各処理系ごとに、最低限XXXbitの大きさは備えた整数型で、最も高速に扱える型の別名として定義されます。例えば、int型が32bitの大きさを持ち、かつ処理系で最も高速な符号付き整数型となっているとしたら、int_fast8_t、int_fast16_t、int_fast32_tはすべてintの別名になるでしょう。
int_fastXXX_tは処理系ごとに定義されるものです。windowsでは、long int=32bit, long long int=64bitなので、int_fast64_tはlong intの別名にはならないのですが、64bit linux gccでは、long int=64bitなので、int_fast64_tはlong intの別名として定義される可能性があるわけです。

かずま

Re: templateの明示的特殊化・intXXX_t型 について

#8

投稿記事 by かずま » 3ヶ月前

tk-xleader さんが書きました:
3ヶ月前
メンバー演算子関数テンプレートの明示的特殊化の書き方はこうです。
そんなこと言われても、そのプログラムは、質問者がちゃんと情報を
提供している次のコンパイラで、エラーになります。
m3908714035 さんが書きました:
3ヶ月前
error: (https://wandbox.org/ C++ gcc HEAD 9.0.0 20181227 (experimental))
コンパイル結果

コード:

Start
prog.cc:9:18: error: explicit specialization in non-namespace scope 'struct my::X'
    9 |         template<> void operator>> <int>(int t)const{
      |                  ^
prog.cc:9:48: error: template-id 'operator>><int>' in declaration of primary template
    9 |         template<> void operator>> <int>(int t)const{
      |                                                ^~~~~
1
Finish
VC++ でエラーにならいないからと言って、それが正しいとは限りません。

アバター
tk-xleader
記事: 153
登録日時: 8年前
連絡を取る:

Re: templateの明示的特殊化・intXXX_t型 について

#9

投稿記事 by tk-xleader » 3ヶ月前

かずま さんが書きました:
3ヶ月前
tk-xleader さんが書きました:
3ヶ月前
メンバー演算子関数テンプレートの明示的特殊化の書き方はこうです。
そんなこと言われても、そのプログラムは、質問者がちゃんと情報を
提供している次のコンパイラで、エラーになります。
m3908714035 さんが書きました:
3ヶ月前
error: (https://wandbox.org/ C++ gcc HEAD 9.0.0 20181227 (experimental))
コンパイル結果

コード:

Start
prog.cc:9:18: error: explicit specialization in non-namespace scope 'struct my::X'
    9 |         template<> void operator>> <int>(int t)const{
      |                  ^
prog.cc:9:48: error: template-id 'operator>><int>' in declaration of primary template
    9 |         template<> void operator>> <int>(int t)const{
      |                                                ^~~~~
1
Finish
VC++ でエラーにならいないからと言って、それが正しいとは限りません。
申し訳ありませんでした。メンバーテンプレートの完全特殊化はclass scopeで定義することはできませんでした(visual c++とclangでは通りますが、これは規格外の独自拡張のようですね)。
正しくは、このように定義することになります。

コード:

#include <iostream>

namespace my{
    struct X{
        template<typename T>
        void operator>>(T)const{
            std::cout<<"primary template."<<std::endl;
        }
    };
    template<> void X::operator>> <int>(int t)const{
        std::cout<<"specialized for int:" << t <<std::endl;
    }
}

int main()
{
    my::X x;
    x >> "";
    x >> 0;
}

返信

“C言語何でも質問掲示板” へ戻る