我希望能够构建一个A或B,而不必考虑构造函数参数的数量。
第二个构造函数不是合法的C ++,但我这样写是为了表达我想要的东西。
是否有一个enable_if技巧可以有选择地启用其中一个构造函数?
(例如,取决于A和B的构造函数参数的数量。)
我需要这个来测试大约15个带有1,2或3个构造函数参数的类。
struct A
{
A(int x)
{
}
};
struct B
{
B(int x, int y)
{
}
};
template<typename T>
struct Adaptor // second constructor is illegal C++.
{
T t;
Adaptor(int x, int y)
: t(x)
{
}
Adaptor(int x, int y) // error: cannot be overloaded
: t(x, y)
{
}
};
int main()
{
Adaptor<A> a(1,2);
Adaptor<B> b(1,2);
return 0;
}
答案 0 :(得分:6)
@Aaron方法的变体:
#include <type_traits>
#include <utility>
enum EArity { EZero = 0, EOne, ETwo, EThree, Error };
template <typename T, typename A1, typename A2, typename A3> struct getArity
{
static const EArity arity =
std::is_constructible<T>::value ? EZero :
std::is_constructible<T, A1>::value ? EOne :
std::is_constructible<T, A1, A2>::value ? ETwo :
std::is_constructible<T, A1, A2, A3>::value ? EThree : Error;
};
template <typename T, EArity A> struct Construct;
template <typename T> struct Construct<T, EZero>
{
T t;
template <typename A1, typename A2, typename A3>
Construct(A1 && a1, A2 && a2, A3 && a3) : t() { }
};
template <typename T> struct Construct<T, EOne>
{
T t;
template <typename A1, typename A2, typename A3>
Construct(A1 && a1, A2 && a2, A3 && a3) : t(std::forward<A1>(a1)) { }
};
// ...
template <typename T>
struct AdapterIntIntInt : Construct<T, getArity<T, int, int, int>::arity>
{
Adapter(int a, int b, int c)
: Construct<T, getArity<T, int, int, int>::arity>(a, b, c) { }
};
template <typename T, typename A1, typename A2, typename A3>
struct Adapter : Construct<T, getArity<T, A1, A2, A3>::arity>
{
Adapter(A1 && a1, A2 && a2, A3 && a3)
: Construct<T, getArity<T, A1, A2, A3>::arity>
(std::forward<A1>(a1), std::forward<A2>(a2), std::forward<A3>(a3))
{ }
};
答案 1 :(得分:2)
另一种变体:
#include <boost/utility/enable_if.hpp>
struct A {
A(int) {}
};
struct B {
B(int, int) {}
};
template <class T>
struct arg_count {
};
template <>
struct arg_count<A> {
const static int count = 1;
};
template <>
struct arg_count<B> {
const static int count = 2;
};
template <class T>
struct Adaptor : public T {
template <class A1, class A2>
Adaptor(A1 a1, A2 a2, typename boost::enable_if_c<arg_count<T>::count == 1, A1>::type* = 0) : T(a1) {}
template <class A1, class A2>
Adaptor(A1 a1, A2 a2, typename boost::enable_if_c<arg_count<T>::count == 2, A2>::type* = 0) : T(a1, a2) {}
};
int main() {
Adaptor<A> a(1, 2);
Adaptor<B> b(1, 2);
}
答案 2 :(得分:1)
使用模板专业化。第一个适配器是“默认”模板,但后者仅用于Adaptor<A>
。
template<typename T>
struct Adaptor
{
T t;
Adaptor(int x, int y)
: t(x,y)
{
}
};
template<>
struct Adaptor<A> {
A t;
Adaptor(int x, int y)
: t(x)
{
}
};