这个问题本质上是来自另一个用户的这个问题的后续问题,它有一些很好的答案: Is it possible to write a template to check for a function's existence?
我想完全按照这个问题所描述的那样做,除了我希望能够为构造函数做到这一点。例如,鉴于这两种类型:
class NormalType
{
public:
NormalType()
{
std::cout << "NormalType::NormalType()" << std::endl;
}
};
class SpecialType
{
public:
SpecialType()
{
std::cout << "SpecialType::SpecialType()" << std::endl;
}
SpecialType(int someArg)
{
std::cout << "SpecialType::SpecialType(int someArg)" << std::endl;
}
};
这个用于构造对象的辅助函数:
template<class T>
class ConstructHelper
{
public:
template<bool HasSpecialConstructor>
static T Construct()
{
return T();
}
template<>
static T Construct<true>()
{
return T(int(42));
}
};
我希望能够编写如下代码:
NormalType normalType = ConstructHelper<NormalType>::Construct<has_special_constructor<NormalType>::value>();
SpecialType specialType = ConstructHelper<SpecialType>::Construct<has_special_constructor<SpecialType>::value>();
如果期望的结果是调用NormalType::NormalType()
,则调用SpecialType::SpecialType(int someArg)
。这里缺少的成分是关键has_special_constructor
帮助器,它可以确定我们的特殊构造函数是否存在于给定类型。
我引用的上一个问题涉及检查某个类型上是否存在给定函数,并且提供了各种工作解决方案。不幸的是,它们中的大多数依赖于能够获取目标方法的地址,并且根据C ++规范,您不能获取构造函数的地址(12.1.10)。在剩下的工作解决方案中,所有这些解决方案似乎都依赖于SFINAE和decltype对模板特化中的任意表达式。这是一个解决这个问题的简单方法,但不幸的是我正在使用Visual Studio 2013,它不能正确支持C ++ 11 SFINAE规则,并且仍然不会发布&#34; Visual Studio 14&#34;无论是。有了正确的SFINAE支持,我应该能够做到这一点,例如:
template<class T>
struct has_special_constructor
{
template<class S>
struct calculate_value: std::false_type {};
template<>
struct calculate_value<decltype(T(int(42)))>: std::true_type {};
static const bool value = calculate_value<T>::value;
};
但是,如果我尝试测试一种没有定义我的目标构造函数的类型,那么由于缺乏SFINAE支持,它不会在VS2013下编译。也就是说,我还不相信这是不可能的,我认为可能有办法让它发挥作用,但到目前为止我还没能找到解决方案。那里的任何人都看到了我忽略的方法吗?
以下是有关我接受答案作为此问题的解决方案所需要的更多信息:
必须可以针对任何给定类型解析has_special_constructor<T>::value
,而无需为该特定类型编写其他代码。
我主要针对Visual Studio 2013,因此任何解决方案都必须在该环境中运行。我知道完全符合C ++ 11的编译器可以更轻松地管理这个问题,但我正在寻找能在我当前的目标编译器上运行的东西。
如果任何人都可以提供在C ++ 03编译器(IE,没有任何C ++ 11功能)的解决方案,我会接受使用C ++ 11功能的解决方案。< / p>
此时我已经满足于基于MSVC扩展的解决方法,因为我可以使用预处理器回退到此方法,直到完全支持C ++ 11。
< / LI>答案 0 :(得分:8)
template<class T>
using has_special_constructor = std::is_constructible<T, int>;
可能的“C ++ 03”版本:
template <class T>
struct has_special_constructor {
typedef char one;
typedef struct { char _[2];} two;
template <std::size_t>
struct dummy {};
template<class U>
static one f(dummy<sizeof(U(42))>*);
template<class>
static two f(...);
static const bool value = sizeof(f<T>(0)) == sizeof(one);
};
这适用于C ++ 03模式下的g ++ 4.4或更高版本。我把“C ++ 03”放在可怕的引号中,因为这取决于表达式SFINAE,seems to be a bit of a gray area in C++03 - 显然C ++ 03的措辞似乎允许它,但没有主要的编译器供应商实际支持它直到C ++ 11几乎就在这里(GCC 4.4于2009年发布),所以“纯粹的”C ++ 03是否允许它是有争议的......