C++17 anyに参照として代入する

#std::any
C++17から登場したstd::anyはどんな型の値でもつっこめる型です

```cpp:main.cpp

#include<iostream>
#include<string>
#include<any>

template<class Type>
void Println(std::any& _any)
{
	if (auto& type = _any.type(); type == typeid(Type))
	{
		std::cout << std::any_cast<Type>(_any) << std::endl;
	}
	else
	{
		std::cout << "can't any_cast" << std::endl;
	}
}

int main()
{
	std::any a;

	a = 2;
	Println<int>(a);

	a = 1.14;
	Println<double>(a);

	a = std::string("hellow");
	Println<std::string>(a);

	return 0;
}
```

#参照として代入するには

```cpp:main.cpp
int main()
{
	int hoge = 0;

	std::any a = hoge;

	std::any_cast<int&>(a)++;

	std::cout << hoge <<std::endl;

	return 0;
}
```
このようなコードを書いても当然`hoge`の値は`0`のままとなります
では、`hoge`も書き換えたい場合どうすればよいのか
##ポインタにしてみる
```cpp:main.cpp
int main()
{
	int hoge = 0;
	std::any a=&hoge;

	(*std::any_cast<int*>(a))++;

	std::cout << hoge<<std::endl;

	return 0;
}
```
タイトルと話がずれますがアドレスを渡してポインタにしてしまうのも一つの手です。
この場合`hoge`も`1`になります
##std::refを使ってみる

```cpp:main.cpp
int main()
{
	int hoge = 0;
	//参照
	std::any a=std::ref(hoge);

	std::any_cast<std::reference_wrapper<int>>(a)++;

	std::cout << hoge<<std::endl;

	//const参照
	a = std::cref(hoge);

	std::cout << std::any_cast<std::reference_wrapper<const int>>(a) << std::endl;

	return 0;
}
```
この方法でも`hoge`の値を書き換えることが可能です。
しかしany_castで`std::reference_wrapper`にしないとうまくキャストできません、気持ち的には`<int&>`や`<const int&>`で扱いたいです。
###any_castをラップする
上のような問題を解決するためにany_castをラップした関数を作ります。

```cpp:
namespace detail
{
	//実装
	template<class T>
	struct AnyCastImpl
	{
		static T Func(std::any& _any)
		{
			using Type = std::remove_const_t<T>;
			if (auto& type = _any.type(); type == typeid(std::reference_wrapper<Type>))
			{
				return std::any_cast<std::reference_wrapper<Type>>(_any);
			}
			else if (type == typeid(std::reference_wrapper<const Type>))
			{
				return std::any_cast<std::reference_wrapper<const Type>>(_any);
			}
			return std::any_cast<T>(_any);
		}
	};
	//参照
	template<class T>
	struct AnyCastImpl<T&>
	{
		static T& Func(std::any& _any)
		{
			if (_any.type() == typeid(std::reference_wrapper<T>))
			{
				return std::any_cast<std::reference_wrapper<T>>(_any);
			}
			return std::any_cast<T&>(_any);
		}
	};
	//const参照
	template<class T>
	struct AnyCastImpl<const T&>
	{
		static const T& Func(std::any& _any)
		{
			if (auto& type = _any.type(); type == typeid(std::reference_wrapper<T>))
			{
				return std::any_cast<std::reference_wrapper<T>>(_any);
			}
			else if (type == typeid(std::reference_wrapper<const T>))
			{
				return std::any_cast<std::reference_wrapper<const T>>(_any);
			}
			return std::any_cast<T&>(_any);
		}
	};
}
//ラップ関数
template<class T>
T any_cast_wrapper(std::any& _any)
{
	return detail::AnyCastImpl<T>::Func(_any);
}

```

`std::reference_wrapper<const T>`→`T&`の変換は不可なので特殊化しておく

使い方は下のような感じ

```cpp:main.cpp

int main()
{
	int hoge = 0;
	//参照
	std::any a=std::ref(hoge);

	any_cast_wrapper<int&>(a)++;		//参照
	any_cast_wrapper<const int&>(a);	//const参照
	int b=any_cast_wrapper<int>(a);		//コピー

	std::cout << hoge<<std::endl;

	//const参照
	a = std::cref(hoge);

	try
	{
		any_cast_wrapper<int&>(a)++;		//参照への変換はbad_any_cast例外
	}
	catch (std::bad_any_cast e)
	{
		std::cout << e.what() << std::endl;
	}

	any_cast_wrapper<const int&>(a);	//const参照
	b = any_cast_wrapper<int>(a);		//コピー

	return 0;
}

```

#まとめ
anyに参照として代入したい場合は、~~諦めてアドレスを渡すか~~、std::refをうまく使う