Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类中存在的成员的模板实例化检查_C++_Class_Templates_Instantiation_Member - Fatal编程技术网

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

C++ 类中存在的成员的模板实例化检查,c++,class,templates,instantiation,member,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 = me

我有一组类,它们有一个或多个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;
}
我现在没有权限实际尝试这个或任何类似的方法,我想知道是否有一种有效的设置方法

我看到过对SFINAE的引用(“替换失败不是一个错误”),但我不确定在这种情况下如何使用它。下面的建议正确吗

这个例子似乎暗示我应该为每个成员创建一个单独的函数,并在没有该成员的情况下使用一个重复的函数

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
}
模板
无效setMemberA(T&myClass,类型A memA)
{
myClass.memberA=memA;
}
模板
作废setMemberA(T&myClass)
{
//这是一个虚拟模板,以避免编译问题
}

这里有一个可能的
设置成员a\u(如果存在)
实现:

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);
}
名称空间详细信息{
模板
如果存在,自动设置成员(T&myClass,typeA memA,int)
->decltype(myClass.memberA=memA,void()){
myClass.memberA=memA;
}
模板
无效集\u memberA\u如果存在\u impl(T&myClass,typeA memA,long){
}
模板
如果存在无效集成员(T&myClass,typeA memA){
详细信息::如果存在,则设置成员a(myClass,memA,0);
}
说明:

SFINAE只适用于函数模板的签名,而不适用于函数模板的主体,因此技巧是在函数模板签名中对检查进行编码。使用C++11尾部返回类型-
->decltype(myClass.memberA=memA,void())很容易做到这一点。
。如果表达式
myClass.memberA=memA
无法编译,则会导致替换失败,并从重载集中删除函数模板。因此,在这种情况下,对
set\u memberA\u的调用(如果存在)\u impl
仍将编译,我们还提供了另一个不做任何事情的重载


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

您可能需要使用SFINAE。@user4098326我已经看到了对它的引用,但无法从我的案例中给出的示例推断。非常聪明,+1。SFINAE发生在
decltype
中,对吗?
是一个很好的旧逗号运算符,您只使用它来计算第一个表达式
myClass.memberA=memA
,对吗?@vsoftco。
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);
}