#include <iostream>
#include <concepts>
#include <vector>
namespace test1 {
template<typename T1, typename T2>
class A {
public:
A() {
std::cout << "A<T1, T2>" << std::endl;
}
};
template<>
class A<char, int> {
public:
A() {
std::cout << "A<char, int>" << std::endl;
}
};
template<typename T2>
class A<char, T2> {
public:
A() {
std::cout << "A<char, T2>" << std::endl;
}
};
template<typename T>
class B {
public:
B() {
std::cout << "B<T>" << std::endl;
}
};
template<>
class B<int> {
public:
B() {
std::cout << "B<int>" << std::endl;
}
};
template<typename T>
class B<std::vector<T> > {
public:
B() {
std::cout << "B<vector<T> >" << std::endl;
}
};
}
namespace test2 {
template<typename T1, typename T2>
void function(const T1& t1, const T2& t2) {
std::cout << "function<T1, T2>" << std::endl;
}
template<>
void function<float, int>(const float& t1, const int& t2) {
std::cout << "function<float, int>" << std::endl;
}
}
namespace test3 {
template<typename T1, typename T2>
class Function {
public:
void operator()(const T1& t1, const T2& t2) {
std::cout << "Function<T1, T2>" << std::endl;
}
};
template<>
class Function<int, char> {
public:
void operator()(const int& t1, const char& t2) {
std::cout << "Function<int, char>" << std::endl;
}
};
template<typename T>
class Function<T, char> {
public:
void operator()(const T& t1, const char& t2) {
std::cout << "Function<T, char>" << std::endl;
}
};
}
namespace test4 {
struct NormalTag {};
struct IntTag {};
template<typename T> struct TagDispatch { using Tag = NormalTag; };
template<> struct TagDispatch<int> { using Tag = IntTag; };
template<typename T1, typename T2>
inline void function_impl(const T1& t1, const T2& t2, NormalTag) {
std::cout << "normal tag" << std::endl;
}
template<typename T1, typename T2>
inline void function_impl(const T1& t1, const T2& t2, IntTag) {
std::cout << "int tag" << std::endl;
}
template<typename T1, typename T2>
void function(const T1& t1, const T2& t2) {
function_impl(t1, t2, typename TagDispatch<T2>::Tag {});
}
}
namespace test5 {
template<typename T1, typename T2>
void function(const T1& t1, const T2& t2) {
std::cout << "default" << std::endl;
}
template<typename T1, typename T2>
requires std::integral<T2>
void function(const T1& t1, const T2& t2) {
std::cout << "use requires" << std::endl;
}
}
int main() {
test1::A<int, int> a1;
test1::A<char, int> a2;
test1::A<char, char> a3;
test1::B<char> b1;
test1::B<int> b2;
test1::B<std::vector<int> > b3;
test2::function(10, 1.0);
test2::function(1.f, 10);
test3::Function<int, int>()(10, 10);
test3::Function<int, char>()(10, '1');
test3::Function<float, char>()(1.f, '1');
test4::function(1, 1.f);
test4::function(1, 2);
test5::function(1, 1.f);
test5::function(1, 111);
return 0;
}
|