2010-01-24 40 views
5

我想知道是否有可能向SFINAE方法延伸到检测一个类是否具有一定的成员函数(如这里所讨论的:如何确定某个类是否具有特定的模板成员函数?

“有C++中的技术知道,如果一个类具有的一个成员函数定签名?” Check if a class has a member function of a given signature

)支持模板成员函数?例如。能够检测在下面的类函数foo:

struct some_class { 
    template < int _n > void foo() { } 
}; 

我想这可能是可能为FOO的特定实例做到这一点,(例如,检查是否void foo<5>()是成员),如下所示:

template < typename _class, int _n > 
class foo_int_checker { 

    template < typename _t, void (_t::*)() > 
    struct sfinae { }; 

    template < typename _t > 
    static big 
    test(sfinae< _t, &_t::foo<_n> > *); 

    template < typename _t > 
    static small 
    test(...); 

public: 

    enum { value = sizeof(test<_class>(0)) == sizeof(big) }; 

}; 

然后做foo_int_checker< some_class, 5 >::value检查some_class是否有成员void foo<5>()。然而在MSVC++ 2008这总是返回false而G ++提供了在该行下面的语法错误test(sfinae< _t, &_t::foo<_n> >);

test.cpp:24: error: missing `>' to terminate the template argument list 
test.cpp:24: error: template argument 2 is invalid 
test.cpp:24: error: expected unqualified-id before '<' token 
test.cpp:24: error: expected `,' or `...' before '<' token 
test.cpp:24: error: ISO C++ forbids declaration of `parameter' with no type 

似乎都失败了,因为我想从一个类型,本身就是得到一个模板函数实例的地址一个模板参数。有谁知道这是可能的还是由于某种原因被标准拒绝?

编辑:看来我错过了::template语法来获得G ++正确编译上面的代码。如果我改变了位在那里我得到了函数的地址&_t::template foo<_n>则程序编译,但我得到了相同的行为,MSVC++(value始终设置为false)。

如果我注释掉...过载的test强制编译器来接的另一个,我得到以g ++以下编译器错误:

test.cpp: In instantiation of `foo_int_checker<A, 5>': 
test.cpp:40: instantiated from here 
test.cpp:32: error: invalid use of undefined type `class foo_int_checker<A, 5>' 
test.cpp:17: error: declaration of `class foo_int_checker<A, 5>' 
test.cpp:32: error: enumerator value for `value' not integer constant 

其中线32是enum { value = sizeof(test<_class>(0)) == sizeof(big) };线。不幸的是这似乎并没有帮我诊断问题:(MSVC++提供了一个类似的不伦不类的错误:。

error C2770: invalid explicit template argument(s) for 'clarity::meta::big checker<_checked_type>::test(checker<_checked_type>::sfinae<_t,&_t::template foo<5>> *)' 

在同一行

什么奇怪的是,如果我从一个特定的获取地址类,而不是一个模板参数(即,而不是&_t::template foo<_n>我做&some_class::template foo<_n>),然后我得到正确的结果,但然后我的检查级仅限于检查该功能的单个类(some_class)。此外,如果我执行以下操作:

template < typename _t, void (_t::*_f)() > 
void 
f0() { } 

template < typename _t > 
void 
f1() { 
    f0< _t, &_t::template foo<5> >(); 
} 

,并呼吁f1<some_class>()然后我没有得到有关&_t::template foo<5>编译错误。这表明,只有在SFINAE上下文中获取模板成员函数的地址和本身是模板参数的类型时,才会出现此问题。哎呀!

+0

C++已经在5年中被破解:D看看http://stackoverflow.com/questions/36780867/i-neet-to-know-at-compilation-time-if-class-a-has- a-function-member-called -b/36780868#36780868 – 2016-04-21 21:34:18

回答

1

有类似的Boost.MPL已经实现的东西,它被称为“BOOST_MPL_HAS_XXX_TRAIT_DEF”。请参阅:

http://www.boost.org/doc/libs/1_41_0/libs/mpl/doc/refmanual/has-xxx-trait-def.html

它可以检测类具有给定名为

也为您的具体情况,而不是传递函数指针作为参数(无效(_t :: *)()),尝试在你的方法,即,类似的身体使用它:

template < typename _t > 
static big test(sfinae<_t>) 
{ 
    &_t::foo<_n>; 
} 
+0

感谢Boost MPL链接。虽然他们似乎没有检测到功能,但他们的方法是相似的,可能会解决我所遇到的问题。我只是现在要分开他们的宏:) 我认为函数指针必须作为编译器的方法签名的一部分获得使用它的重载决议。当我将它移入方法时,编译器总是选择测试的“大”重载,因此即使函数不存在,“值”也是如此。 – Aozine 2010-01-26 20:11:26

相关问题