我试图检测一个类是否有一个特定的函数(具体来说是std::enable_shared_from_this<Some Unknown Class> shared_from_this() ,它是从std::enable_shared_from_this<Some Unknown Class>inheritance的)。 为了使事情更加复杂,我需要知道它是否具有这个function,即使它是从远处的基类inheritance的,或者是使用受保护的访问inheritance的。 我已经看过其他问题,比如这个 ,但是提供的方法不适用于检测受保护的成员函数。 目前我正在使用的方法如下: template <class T> struct shared_from_this_wrapper : public T { template <class U> static auto check( U const & t ) -> decltype( t.shared_from_this(), std::true_type() ); static auto check( … ) -> decltype( std::false_type() ); }; template<class T> struct has_shared_from_this : decltype(shared_from_this_wrapper<T>::check(std::declval<shared_from_this_wrapper<T>>())) { }; 我目前的解决scheme的缺陷是,它不适用于final宣布的类。 […]
在http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx,VC ++团队正式声明他们还没有实现C ++ 11核心function“Expression SFINAE”。 但是,从http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2634.html复制的以下代码示例已被VC ++编译器接受。 例1: template <int I> struct A {}; char xxx(int); char xxx(float); template <class T> A<sizeof(xxx((T)0))> f(T){} int main() { f(1); } 例2: struct X {}; struct Y { Y(X){} }; template <class T> auto f(T t1, T t2) -> decltype(t1 + t2); // #1 X f(Y, Y); // […]
我在这里find的代码看起来像这样: auto f(T& t, size_t n) -> decltype(t.reserve(n), void()) { .. } 在我读的所有文档中,我被告知decltype被签名为: decltype( entity ) 要么 decltype( expression ) 而且在任何地方都没有第二个论点。 至less这是cppreference指向的内容。 这是decltype的第二个参数吗? 如果是这样,它是做什么的?
Scott Meyers发表了他的下一本书EC ++ 11的内容和状态 。 他写道,书中的一个项目可能是“避免函数签名中的std :: enable_if”。 std::enable_if可以用作函数参数,作为返回types或作为类模板或函数模板参数来有条件地从重载parsing中移除函数或类。 在这个问题中,所有三个解决scheme都显示 作为函数参数: template<typename T> struct Check1 { template<typename U = T> U read(typename std::enable_if< std::is_same<U, int>::value >::type* = 0) { return 42; } template<typename U = T> U read(typename std::enable_if< std::is_same<U, double>::value >::type* = 0) { return 3.14; } }; 作为模板参数: template<typename T> struct Check2 { […]
编辑,为了避免混淆: decltype不接受两个参数。 查看答案。 在编译期间,可以使用以下两个结构来检查typesT上成员函数的存在: // Non-templated helper struct: struct _test_has_foo { template<class T> static auto test(T* p) -> decltype(p->foo(), std::true_type()); template<class> static auto test(…) -> std::false_type; }; // Templated actual struct: template<class T> struct has_foo : decltype(_test_has_foo::test<T>(0)) {}; 我认为这个想法是在检查成员函数的存在时使用SFINAE,所以在p->foo()无效的情况下,只定义返回std::false_type的test的椭圆版本。 否则,第一个方法被定义为T* ,并将返回std::true_type 。 实际的“开关”发生在第二个类中,它inheritance自test返回的types。 与is_same等不同的方法相比,这看起来很聪明和“轻量级”。 有两个参数的decltype首先让我感到惊讶,因为我认为它只是得到了一个expression式的types。 当我看到上面的代码时,我认为它是“试图编译expression式,并总是返回第二种types,如果expression式编译失败,则失败”(所以隐藏这个特殊化; SFINAE)。 但: 然后我想我可以用这个方法来写任何“有效的expression式”检查器,只要它依赖于某种types的T 例: … template<class T> static auto […]
什么是C ++中的SFINAE? 你可以用一个对C ++不熟练的程序员来解释吗? 此外,SFINAE对应于像Python这样的语言中的什么概念?
我想进入更多的模板元编程。 我知道SFINAE代表“替代失败不是一个错误”。 但有人可以给我看SFINAE的好用吗?
我想创build一个例子,这将检查operator== (成员或非成员函数)的存在。 要检查一个类是否有成员operator==很容易,但是如何检查它是否有一个非成员operator== ? 这就是我所需要的: #include <iostream> struct A { int a; #if 0 bool operator==( const A& rhs ) const { return ( a==rhs.a); } #endif }; #if 1 bool operator==( const A &l,const A &r ) { return ( la==ra); } #endif template < typename T > struct opEqualExists { struct yes{ char […]
C ++ 11标准第14.8.2 / 8段规定了replace失败应该或不应该导致“硬”编译错误(从而导致编译失败)或“软”错误的条件导致编译器从重载parsing的候选集合中丢弃一个模板(不会使编译失败,并启用众所周知的SFINAE成语): 如果replace导致无效的types或expression式,则键入演绎失败。 无效的types或expression式是使用replace参数编写的格式不正确的types或expression式。 [注意:访问检查是替代过程的一部分。 -end note] 只有函数types及其模板参数types的上下文中的无效types和expression式才会导致扣除失败 。 […] 在“整个C ++ 11标准”中,“ 直接上下文 ”这个词只出现了8次,每次它们跟随(或作为其一部分出现)下列(非规范性)文本的实例: [注意: 替代types和expression式的评估可能导致副作用,例如类模板特化和/或函数模板特化的实例化,隐式定义函数的生成等。这些副作用不在“即时上下文“,并可能导致程序不合格。 – 注意] 这个注释给出了直接上下文意味着什么(不是非常慷慨的)暗示,但是至less对于我来说,这往往不足以决定replace是否应该导致“硬”编译错误。 题: 你能提供一个解释,一个决策程序,和/或一些具体的例子来帮助搞清楚在哪些情况下,replace错误在函数types及其模板参数types的“ 直接上下文 ”中是否发生?
在这个答案中,我定义了一个基于types的is_arithmetic属性的模板: template<typename T> enable_if_t<is_arithmetic<T>::value, string> stringify(T t){ return to_string(t); } template<typename T> enable_if_t<!is_arithmetic<T>::value, string> stringify(T t){ return static_cast<ostringstream&>(ostringstream() << t).str(); } dyp表明 ,而不是该types的is_arithmetic属性,是否为该types定义了to_string是模板select条件。 这显然是可取的,但我不知道这样说: 如果未定义std::to_string则使用ostringstream重载。 声明to_string条件很简单: template<typename T> decltype(to_string(T{})) stringify(T t){ return to_string(t); } 这是与我无法弄清楚如何构build的标准相反的。 这显然不起作用,但希望它传达了我想要构build的东西: template<typename T> enable_if_t<!decltype(to_string(T{})::value, string> (T t){ return static_cast<ostringstream&>(ostringstream() << t).str(); }