模板实例化检查类中存在的成员

时间:2015-02-22 02:25:56

标签: c++ class templates instantiation member

我有一组具有一个或多个memberA,memberB,memberC类型成员的类。并非所有课程都包含所有成员。我想创建一个模板,用于设置

等成员
template <typename T>
void setAttributes(t & myClass, typeA memA, typeB memB, typeC memC)
{
  myClass.memberA = memA;
  myClass.memberB = memb;
  myClass.memberC = memC;
}

显然,在尝试实例化缺少其中一个成员的类时,这将在编译时失败。是否存在#if或类似的东西,允许对表单的条件编译进行检查

#ifdef myClass.memberA
  myClass.memberA = memA;
#endif

我现在无法访问实际尝试此类或类似内容,我想知道是否有一种有效的设置方式。

我见过对SFINAE的引用(&#34;替换失败不是错误。&#34;)但我不确定在这种情况下如何使用它。以下建议是否正确?

Substitution failure is not an error示例似乎暗示我应该为没有该成员的具有重复功能的每个成员创建单独的函数。

template <typename T>
void setMemberA(T & myClass, typeA memA)
{
  myClass.memberA = memA;
}

template <typenum T>
void setMemberA(T & myClass)
{
  // This is a dummy template to avoid a compilation problem
}

1 个答案:

答案 0 :(得分:3)

这是一个可能的set_memberA_if_exists实现:

namespace details {
    template<class T>
    auto set_memberA_if_exists_impl(T & myClass, typeA memA, int) 
         -> decltype(myClass.memberA = memA, void()) {
        myClass.memberA = memA;
    }

    template<class T>
    void set_memberA_if_exists_impl(T & myClass, typeA memA, long) {}
}

template<class T>
void set_memberA_if_exists(T & myClass, typeA memA) {
     details::set_memberA_if_exists_impl(myClass, memA, 0);
}

说明:

SFINAE仅适用于函数模板的签名,而不是正文,因此诀窍是在函数模板签名内对检查进行编码。使用C ++ 11尾随返回类型 - -> decltype(myClass.memberA = memA, void())很容易。如果表达式myClass.memberA = memA无法编译,则会导致替换失败并从重载集中删除函数模板。因此,在这种情况下,对set_memberA_if_exists_impl的调用仍然会编译,我们还提供另一个do-nothing过载。

当它们都可行时,我们还需要一种方法来区分这两个重载。这是通过引入第三个参数来完成的。 do-something重载的第三个参数的类型是int,而do-nothing重载的是long。当我们调用它时,通过提供0(一个int)作为第三个参数,我们确保在可行的情况下首选do-something重载。