【发布时间】:2013-04-21 23:52:47
【问题描述】:
有谁知道如何检测带有一个参数的构造函数?例如,这个结构应该有一个否定的结果:
struct MyStruct
{
MyStruct( int x, int x2 ) : y( x ) {}
int y;
};
我在这里有一个很好的 SFINAE 检查来查看一个类或结构是否作为具有特定数量参数的构造函数。这是参数计数为 3 的那个:
template <typename T>
struct HasCtor3Args
{
struct Any { template <typename U> operator U( void ); };
template <typename U>
static int32 SFINAE( decltype( U( Any( ), Any( ), Any( ) ) ) * );
template <typename U>
static int8 SFINAE( ... );
static const bool value = sizeof( SFINAE<T>( NULL ) ) == sizeof( int32 );
};
这似乎工作得很好,因为Any 结构可以转换为参数应该是的任何类型。然而,问题是当试图检测一个只有一个参数的构造函数时。由于默认 Any 为与 T 相同的类型,因此 SFINAE 检查似乎总是返回 true,从而检测到复制构造函数。
编辑和更新: 我做了一些尝试,似乎都没有成功......这是我能得到的最接近的结果,但它不起作用,因为它总是返回 true。这个想法是尝试让复制构造函数解析而不是第一个“catch all”调用:
template <typename T>
struct HasCtor1Args
{
struct Any
{
template <typename U>
operator U( ) const;
};
template <typename U>
static int32 SFINAE( decltype( U( Any( ) ) ) * );
// Try to catch the copy ctor here
T MakeT( void );
template <typename U>
static int8 SFINAE( decltype( U( MakeT( ) ) ) * );
template <typename U>
static int8 SFINAE( ... );
static const bool value = sizeof( SFINAE<T>( NULL ) ) == sizeof( int32 );
};
我还尝试使用显式关键字以及 C++11 的 = delete 功能,然后意识到我需要使用的编译器(微软的)不允许这样做。我也尝试在转换类型 U 上使用 std::enable_if,虽然我遇到了不能默认函数模板参数的错误。
【问题讨论】:
-
由于某种原因,它在转换运算符明确时起作用:
template < typename U > explicit operator U() const;。我不得不在标准中查找这个,但这可能是 g++ 4.8 中的一个错误。 -
嗯,我不认为使用这样的显式方法可以在微软的编译器上工作。
-
如果有两个单参数构造函数,替换将失败。我认为没有办法解决它。
-
好吧,我将其解释为“只接受一个参数”,或者等效地,“只有一个参数”;)
标签: c++ templates metaprogramming sfinae