# 简单的C++Concept实现:给模板参数加限制

1.背景
#include <iostream>
using namespace std;
typedef long long int64;

struct BigInteger {
BigInteger(int64 v): value(v) {}
int64 value;
};

template<typename T>
BigInteger operator * (T v, const BigInteger& x) {
return BigInteger((int64)v * x.value);
}

struct Matrix {
};

int main() {
Matrix a;
BigInteger b(1);
a * b;
return 0;
}

concept.c: In instantiation of 'BigInteger operator*(T, const BigInteger&) [with T = Matrix]':
concept.c:21:7:   required from here
concept.c:12:21: error: invalid cast from type 'Matrix' to type 'int64 {aka long long int}'
return BigInteger((int64)v * x.value);

2.实现

#include <iostream>
#include <type_traits>
using namespace std;
typedef long long int64;

template<int ok>
struct CheckConditionThen{};

template<>
struct CheckConditionThen<true>{
template<typename U>
struct IdenticalType {
typedef U type;
};
};

#define REQUIRES(...) typename CheckConditionThen<__VA_ARGS__>::
#define RETURN(...) template IdenticalType<__VA_ARGS__>::type

struct BigInteger {
BigInteger(int64 v): value(v) {}
int64 value;
};

template<typename T>
REQUIRES(is_integral<T>::value)
RETURN(BigInteger)
operator * (T v, const BigInteger& x) {
return BigInteger((int64)v * x.value);
}

struct Matrix {
};

int main() {
Matrix a;
BigInteger b(1);
a * b;
return 0;
}

concept1.c: In function 'int main()':
concept1.c:38:5: error: no match for 'operator*' (operand types are 'Matrix' and 'BigInteger')
a * b;
~~^~~
concept1.c:28:1: note: candidate: template<class T> typename CheckConditionThen<std::is_integral<_Tp>::value>::IdenticalType<BigInteger>::type operator*(T, const BigInteger&)
operator * (T v, const BigInteger& x) {
^~~~~~~~
concept1.c:28:1: note:   template argument deduction/substitution failed:
concept1.c: In substitution of 'template<class T> typename CheckConditionThen<std::is_integral<_Tp>::value>::IdenticalType<BigInteger>::type operator*(T, const BigInteger&) [with T = Matrix]':
concept1.c:38:7:   required from here
concept1.c:28:1: error: no class template named 'IdenticalType' in 'struct CheckConditionThen<0>'

3.分析

input T => filter T => output T会更加优美:

template<typename T>
struct IdenticalType {
typedef T type;
};

template<int v>
struct IdenticalValue {
enum {value = v};
};

template<typename T, int ok>
struct CheckCondition {
};

template<typename T>
struct CheckCondition<T, 1> {
typedef T type;
};

#define RETURN(...) typename CheckCondition<typename IdenticalType<__VA_ARGS__>::type,
#define WHEN(...) IdenticalValue<__VA_ARGS__>::value >::type

template<int ok, typename T>
struct IdenticalIfTrue {
};

template<typename T>
struct IdenticalIfTrue<1, T> {
template<typename U>
struct IdenticalType {
typedef U type;
};
};

template<typename T>
struct CheckCondition {
template<int ok>
struct IdenticalIfTrueWrapper {
typedef typename IdenticalIfTrue<ok, T>::template IdenticalType<T>::type type;
};
};

#define RETURN(...) typename CheckCondition<__VA_ARGS__>::

#define WHEN(...) IdenticalIfTrueWrapper<__VA_ARGS__>::type

4.不足