質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2917閲覧

c[c++] テンプレート関数の特殊化について

yama_da

総合スコア73

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/05/05 14:04

こんばんは。テンプレート関数の特殊化についてわからない部分があるので、教えてください。
テンプレート関数の特殊化の例として、以下のようなものが書けますが、

c++

1#include <iostream> 2 3class Hoge 4{ 5public: 6 template <typename T> 7 void TemplateFunction() 8 { 9 std::cout << "TemplateFunction() :: normal version!" << '\n'; 10 } 11}; 12 13/** 14 * int,float に対して特殊化 15 */ 16template <> 17void Hoge::TemplateFunction<int>() 18{ 19 std::cout << "TemplateFunction() :: int version!" << '\n'; 20} 21 22template <> 23void Hoge::TemplateFunction<float>() 24{ 25 std::cout << "TemplateFunction() :: float version!" << '\n'; 26} 27 28 29/** 30 * main() 31 */ 32 33int main(int argc, char const *argv[]) { 34 35 Hoge hoge; 36 std::cout << "Hoge class test" << '\n'; 37 hoge.TemplateFunction<double>(); 38 hoge.TemplateFunction<int>(); 39 hoge.TemplateFunction<float>(); 40 41 return 0; 42} 43

< 実行結果 >

Hoge class test TemplateFunction() :: normal version! TemplateFunction() :: int version! TemplateFunction() :: float version!

この特殊化は1つの型に対して1つの特殊化された関数というようになっています。僕のやりたいのはこれではなく、複数種類の型に対して特殊化された関数を1つ作るということがしたいです。例えば、

c++

1class Hoge 2{ 3public: 4 template <typename T> 5 void TemplateFunction() 6 { 7 std::cout << "TemplateFunction() :: normal version!" << '\n'; 8 } 9}; 10 11/** 12 * int,float に対して特殊化 13 */ 14template <> 15void Hoge::TemplateFunction<int>() 16{ 17 std::cout << "TemplateFunction() :: int version!" << '\n'; 18} 19 20template <> 21void Hoge::TemplateFunction<float>() 22{ 23 std::cout << "TemplateFunction() :: float version!" << '\n'; 24} 25 26/** 27 * typename T = double または char の時はこっちが呼ばれる 28 */ 29template <> 30void Hoge::TemplateFunction<double or char>() 31{ 32 std::cout << "TemplateFunction() :: double or char version!" << '\n'; 33}

このように、テンプレート引数がdoubleまたはcharのときは1番下の関数が呼ばれるようにしたいのです。double、char型それぞれに対して全く同じ中身のTemplateFunction<double>()TemplateFunction<char>()を定義すれば実現できますが、これだと中身が同じ内容の関数をいくつも書くことになってしまいます。他に方法はないでしょうか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

こんにちは。

オーバーロードを使えばできないことはないです。
MinGW 5.3.0 -std=c++11とmsvc 2015で走りました。

C++

1#include <iostream> 2#include <type_traits> 3 4#define OVERLOAD(...) typename std::enable_if<__VA_ARGS__, std::nullptr_t>::type=nullptr 5 6class Hoge 7{ 8public: 9 template <typename T, OVERLOAD(!(std::is_same<T, double>::value || std::is_same<T, char>::value))> 10 void TemplateFunction() 11 { 12 std::cout << "TemplateFunction() :: normal version!" << '\n'; 13 } 14 15 template <typename T, OVERLOAD((std::is_same<T, double>::value || std::is_same<T, char>::value))> 16 void TemplateFunction() 17 { 18 std::cout << "TemplateFunction() :: double or char version!" << '\n'; 19 } 20}; 21 22/** 23 * int,float に対して特殊化 24 */ 25template <> 26void Hoge::TemplateFunction<int>() 27{ 28 std::cout << "TemplateFunction() :: int version!" << '\n'; 29} 30 31template <> 32void Hoge::TemplateFunction<float>() 33{ 34 std::cout << "TemplateFunction() :: float version!" << '\n'; 35} 36 37#if 0 38/** 39 * typename T = double または char の時はこっちが呼ばれる 40 */ 41template <> 42void Hoge::TemplateFunction<double or char>() 43{ 44 std::cout << "TemplateFunction() :: double or char version!" << '\n'; 45} 46#endif 47 48int main(int argc, char const *argv[]) { 49 50 Hoge hoge; 51 std::cout << "Hoge class test" << '\n'; 52 hoge.TemplateFunction<double>(); 53 hoge.TemplateFunction<char>(); 54 hoge.TemplateFunction<int>(); 55 hoge.TemplateFunction<float>(); 56 57 return 0; 58}

投稿2017/05/05 14:27

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yama_da

2017/05/05 15:05

回答ありがとうございます。 マクロ`OVERLOAD(...)`の中身がわからないのですが、 `(std::is_same<T, double>::value || std::is_same<T, char>::value)` がtrueの時は ```c++ template <typename T, OVERLOAD((std::is_same<T, double>::value || std::is_same<T, char>::value))> void TemplateFunction() { std::cout << "TemplateFunction() :: double or char version!" << '\n'; } ``` の方を実体化?して、そうでないときはもう一方の関数のほうを実体化?するということでしょうか?
Chironian

2017/05/05 15:15

その通りです。(用語も実体化instantiationでOKです。) マクロはC++11で拡張された可変長引数を使ってます。単なる手抜きです。__VA_ARGS__が実引数に置き換わります。 そう言えば、上記ソースの場合、実引数を()で括っているので↓でも問題ないです。 #define OVERLOAD(x) typename std::enable_if<x, std::nullptr_t>::type=nullptr これで、実引数を()で括ってない場合は、実引数の途中で ,(カンマ)がでてくるので、引数の個数違いエラーになります。
yama_da

2017/05/05 15:48

ありがとうございます。 もうひとつお聞きしたいのですが、テンプレートクラス内のメンバ関数に対してこれと同じことをしたいときはどのように書けば良いのでしょうか?
Chironian

2017/05/05 18:28

↓が参考になると思います。 http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml#temp.class クラス内で定義が可能な時は普通のクラスの中で定義する時と同じです。 クラス外で定義が必要な時(特殊化など)は、template<typename U> class Hoge { };ならば、次のようにすればできると思います。(記憶で書いているので外していたらごめんなさい。) template<typename U> template <> void Hoge<U>::TemplateFunction<int>() { // 特殊化定義 }
yama_da

2017/05/05 23:12

大変助かりました、なんとか上手くいきました。 また機会があればよろしくお願いします。ありがとうございました!
guest

0

doubleとcharというのが分かりませんが、そういう場合は、doubleとchar共通の関数を作っておいてテンプレートから呼び出す形になるのではないでしょうか?

投稿2017/05/05 14:07

yoorwm

総合スコア1305

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問