0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

using declarationとADLに関する覚書

Posted at

using declarationは、その名の通り宣言なので、ある名前空間で他の名前空間の関数をusing宣言すると、その関数はADLによって呼ばれる可能性が生じる。

#include <iostream>

void print(void){}

namespace ns1{
	template<typename T>
	void print(T const& obj){
		std::cout << obj <<std::endl;
	}
}

namespace ns2{
	struct foo{
		int bar = 0;
		friend std::ostream& operator<<(std::ostream& o, foo const& obj){
			return o << obj.bar;
		}
	};
	using ::ns1::print;
}

int main() {
	print(ns2::foo{}); //ns1::printが呼ばれる。
	return 0;
}

逆に、他の名前空間に属する関数をADLで呼び出せるようにしたい場合、これを利用できる。例えば、std::rel_ops名前空間内の関数テンプレートは、これを応用するのが最善の活用方法だと思われる(もっとも、std::rel_opsはC++2aでdeprecatedになる)。

#include <iostream>
#include <utility>

namespace my{
	namespace _impl{
		struct foo{
			int bar = 0;
			bool operator==(foo other)const{
				return bar == other.bar;
			}
			bool operator<(foo other)const{
				return bar < other.bar;
			}
		};
		
		using std::rel_ops::operator!=;
		using std::rel_ops::operator<=;
		using std::rel_ops::operator>;
		using std::rel_ops::operator>=;
	}
	typedef _impl::foo foo;
}

int main() {
	my::foo foo1{100}, foo2{1000};
	std::cout << std::boolalpha;
	std::cout << (foo1 != foo2) <<std::endl;
	std::cout << (foo1 <= foo2) <<std::endl;
	std::cout << (foo1 >  foo2) <<std::endl;
	std::cout << (foo1 >= foo2) <<std::endl;
	return 0;
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?