C++  "オブジェクト.template  method<型>(  )"　の意味がわからなかったので調べてみた(dot template)

# 概要

C++の線形代数ライブラリである**Eigen**のドキュメントのExampleをいろいろと試していたところ、以下のコードが出てきた。

```C++
#include <iostream>
#include <Eigen/Dense>
 
int main()
{
   Eigen::MatrixXf A = Eigen::MatrixXf::Random(3, 2);
   std::cout << "Here is the matrix A:\n" << A << std::endl;
   Eigen::VectorXf b = Eigen::VectorXf::Random(3);
   std::cout << "Here is the right hand side b:\n" << b << std::endl;
   std::cout << "The least-squares solution is:\n"
        << A.template bdcSvd<Eigen::ComputeThinU | Eigen::ComputeThinV>().solve(b) << std::endl;
}
```

最後の文
```C++
A.template bdcSvd<Eigen::ComputeThinU | Eigen::ComputeThinV>().solve(b)
```
が全く理解できずにいたが、さらにコンパイルエラーにもなったので記載ミスかとも思ったが調べてみることにした。**.template** は**dot template**と言うみたいです。

追記)
コメント欄に[@SaitoAtsushiさんの解説](https://qiita.com/h6591/items/8650d00fa90f83c46886#comment-0c8d9a5fef9c9b4dd8cf)がありますので、コメント欄も御覧ください。

# 実行環境

```terminal
> g++ --version
Apple clang version 16.0.0 (clang-1600.0.26.6)
Target: arm64-apple-darwin24.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
```

# dot templateの調査

## 参照記事

https://karino2.github.io/2020/11/24/template_as_a_keyword.html

https://cpprefjp.github.io/lang/cpp11/dependent_name_specifier_outside_of_templates.html#relative-page

## 実験

参照記事の２番目のサンプルコードに出力のコード追加して試してみます。

```c++:test1.cc
#include <iostream>
#include <vector>

struct X {
  template <int N>
  int get() const
  {
      return N;
  }
};

int main()
{
  typename std::vector<int>::iterator it; // OK

  int value = X().template get<3>(); // OK
  std::cout << "value = " << value << std::endl;
}
```

記事は**C++11**のところに記載されていたので、**C++11**以上なら大丈夫なようです。

```terminal
> g++ test1.cc -std=c++11
> ./a.out
value = 3
```

上記のコードを今までのように書くとしたら、以下のようになるでしょう。

```c++:test2.cc
#include <iostream>
#include <vector>

struct X {
  template <int N>
  int get() const
  {
      return N;
  }
};

int main()
{
  std::vector<int>::iterator it;

  int value = X().get<3>(); 
  std::cout << "value = " << value << std::endl;
}
```
```terminal
> g++ test2.cc -std=c++03
> ./a.out
value = 3
```
C++03でもコンパイルエラーはなかった。

今度は**template**を使った関数**print**の中で試す。

```c++:test3.cc
#include <iostream>
#include <vector>

struct X {
  template <int N>
  int get() const
  {
      return N;
  }
};


template<typename T> void print(T& x) {
  int value = x.get<3>(); 
  std::cout << "value = " << value << std::endl;
}

int main()
{
  typename std::vector<int>::iterator it; 
  X xx  = X();
  print<X>(xx);
}
```

```terminal
> g++ test3.cc -std=c++11
test3.cc:14:17: error: missing 'template' keyword prior to dependent template name 'get'
   14 |   int value = x.get<3>(); 
      |                 ^  ~~~
1 error generated.
```
エラーになりました。
では、**dot template**に戻してみます。

```c++:test4.cc
#include <iostream>
#include <vector>

struct X {
  template <int N>
  int get() const
  {
      return N;
  }
};


template<typename T> void print(T& x) {
  int value = x.template get<3>();
  std::cout << "value = " << value << std::endl;
}

int main()
{
  typename std::vector<int>::iterator it;
  X xx = X();
  print<X>(xx);
}
```
```terminal
> g++ test4.cc -std=c++11
> ./a.out
value = 3
```
**dot template**なら無事にコンパイルできました。

もう一つだけ試してみます。

```c++:test5.cc
#include <iostream>
#include <vector>

struct X {
  template <int N>
  int get() const
  {
      return N;
  }
};


template<typename T>T print(X& x) {
  int value = x.get<3>();
  std::cout << "value = " << value << std::endl;
  return (T)value;
}

int main()
{
  typename std::vector<int>::iterator it;
  X xx = X();
  print<int>(xx);
}
```
**T**の**template**はなくても良かったのですが、一応残しました。
```terminal
> g++ test5.cc -std=c++11
> ./a.out
value = 3
```
今までの使い方も確認できて良かったです。


**template**で指定された型のオブジェクトのメンバーに**template**が使われているときは
**dot templat**を使わないといけないのではないか、というのが自分なりの理解です。たぶん、これは１番目の参照記事が言っている事だとは思います。

# 終わりに

最初検索などをしても**template**で検索するとたくさん出てくるので、自分が知りたいものが**dot template**だと分かるまでに時間がかかりました。さらに、**dot template**の記事も少ないという状況でした。