TechsMex

技術エンジニア C++/Python/Java

テンプレートクラス内のusingによるエイリアス宣言について

背景

以下のようなテンプレートクラスにおいて、
使用する型を短縮したい場合がある。
例えばコンテナ型を用いる場合、テンプレートが入れ子になって
ごちゃごちゃして見づらい。

template <class T, class K>
class ScoreTable
{
public:
  // 型名が長すぎる
  using Dmap = std::unordered_map<T, std::unordered_map<K, int>>;
  int GetScore(T row, K col);
  void SetScore(T row, K col, int val);
  void SetDmap(Dmap &dmap);

private:
  std::unordered_map<T, std::unordered_map<K, int>>dmap_;
};

これをこうしたい。

// どこかで以下を宣言
using Dmap = std::unordered_map<T, std::unordered_map<K, int>>;
// 型がすっきりに
template <class T, class K>
class ScoreTable
{
public:
  int GetScore(T row, K col);
  void SetScore(T row, K col, int val);
  void SetDmap(Dmap &dmap);

private:
  Dmap dmap_;
};

問題点

テンプレートクラスで使うためにはグローバル空間で
using宣言はできない?と考えclass内でusing宣言にする作戦。
ただ、void SedDmap()関数は引数に Dmap型を使うため、
外部にDmap型を知らせるのかわからなかった。

結論

classのpublicに型エイリアスを宣言する。
エイリアスをクラスから参照できることを知らなかった。

適当にクラス内で宣言して使っていたが、
privateになっていることが頭から抜けていた。

ソースコード

double_map.h

#ifndef DOUBLE_MAP_H_
#define DOUBLE_MAP_H_

#include <unordered_map>

template <class T, class K>
class ScoreTable
{
public:
  using Dmap = std::unordered_map<T, std::unordered_map<K, int>>;
  int GetScore(T row, K col);
  void SetScore(T row, K col, int val);
  void SetDmap(Dmap &dmap);

private:
  Dmap dmap_;
};

template <class T, class K>
int ScoreTable<T, K>::GetScore(T row, K col)
{
  return dmap_.at(row).at(col);
}

template <class T, class K>
void ScoreTable<T, K>::SetScore(T row, K col, int val)
{
  dmap_.insert({row, {}});
  dmap_[row].insert({col, val});
}

template <class T, class K>
void ScoreTable<T, K>::SetDmap(Dmap &dmap)
{
  dmap_ = std::move(dmap);
}
#endif

上記クラスを使う側

double_map.cc

#include <iostream>
#include <string>
#include "double_map.h"

int main()
{
  using Stbl = ScoreTable<std::string, std::string>;
  Stbl dmap;
  Stbl::Dmap set_map = {{"Tom", {{"english", 95}, {"math", 75}}},
                        {"Jaws", {{"english", 63}, {"math", 52}}}};
  dmap.SetDmap(set_map);
  std::string student = "Tom";
  std::string subject = "math";
  std::cout << student << " : " << subject << " : score : ";
  std::cout << dmap.GetScore(student, subject) << std::endl;

  return 0;
}

出力

Tom : math : score :75