2015-02-23 202 views
0

我有很多的班级,不同的成员,所有这一切有我,询问如何建立通用模板来执行这些操作如下类型C++模板变量类型声明

::basedata::Maindata maindata; 
::basedata::Subdata subinfo("This goes into the subinfo vector"); 
subinfo.contexts(contextInfo); 
maindata.subdata().push_back(subinfo); 

注意的操作。我无法为每种类型的maindata和subinfo设置一个特例。我也需要能够看到如何从我的主代码中调用模板。如果 maindata.subdata()存在,但我一直能够建立一个模板,但如果它不存在,则在对该模板的调用中保持编译失败。那就是创建表格的模板

perform_Push(maindata.subdata(), subinfo); 

这样就可以编译maindata.subdata()是否存在。

我可以接受,建立模板,使主代码可以显示

bool retval 
retval = hasmember(maindata, subdata); 
if (retval) 
    { 
    buildmember(maindata.subdata, subinfo); 
    setAttributes(subinfo, data); 
    perform_Push(maindata.subdata(), subinfo) 
    } 
else 
    { 
    // Perform alternate processing 
    } 

截至目前,内如果不编译代码时被调用模板应该仅仅是无效的。

While :: basedata :: Maindata总是被定义的,:: basesata :: Subdata可能会或可能不会被定义,这取决于我的代码正在使用的库的版本。子数据被定义为属于maindata的矢量,因此它具有定义的push_back()操作。在任何情况下,都有太多类型的subData为模板中的每个类型创建一个单独的模板作为T :: Subdata。

也就是说,如果子数据是唯一的情况下,我可以创建模板T的专业化为:: maindata ::子数据和通用模板T.

我没有包含文件的任何控制或库,这样我就不能创建一个变量的#define来用预编译器进行测试。有没有一种设置模板的好方法,可以让它起作用?我可以使用返回布尔型true(成功)或false(无此类定义)的模板,并在运行时调用备用处理。我不需要有替代模板。

基本上,我问的是如何将SFINAE应用于这种特殊情况。

我设法找出我需要做的设置基本模板

如果我有最基本的操作

maindata.subdata().push_back(data) 

我可以定义表单模板,

<template class T, typename D> 
auto doPush(D data) -> decltype(T.pushback(data), void()) 
{ 
    T.push_back(data); 
} 

和通话将

doPush<maindata.subdata()>(data); 

但是,问题将是如何设置时,maindata还没有成员的子数据。

+0

看一看型性状和SFINAE – OMGtechy 2015-02-23 18:36:36

+0

我不知道你问:也许http://stackoverflow.com/questions/18701798/building-and-accessing-a-list-of -types-at-compile-time/18704609#18704609 – 2015-02-23 18:43:49

+0

@DieterLücking我会看看问题和答案,看看它是否可以提供帮助。 – sabbahillel 2015-02-23 18:55:38

回答

1

您可以使用此模板来获取布尔值,告诉您是否存在Subdata类型的普通类型T。这只在T是一个结构/类而不是名称空间时才有效。

#include <type_traits> 

template <class T, class V = void> 
    struct hasSubdata 
    { 
    enum { value = false }; 
    }; 

template <class T> 
    struct hasSubdata<T, typename std::enable_if< std::is_same<typename T::Subdata, typename T::Subdata>::value >::type> 
    { 
    enum { value = true }; 
    }; 


struct basedata1 
{ 
    struct Subdata {}; 
}; 

struct basedata2 
{ 

}; 

#include <iostream> 

int main() 
{ 
    std::cout << "basedata1: " << hasSubdata<basedata1>::value << std::endl; 
    std::cout << "basedata2: " << hasSubdata<basedata2>::value << std::endl; 
} 

但是,如果因为编译器检查所​​有可能性的正确性,你不能使用正常。 你有类似的方式(非常丑陋)采取行动:

template <class T, bool = hasSubdata<T>::value> 
    struct SubdataUser 
    { 
    static void foo() 
    { 
     std::cout << "I can use SubData member :)" << std::endl; 

     typename T::Subdata subinfo(); 
    }   
    }; 

template <class T> 
    struct SubdataUser<T, false> 
    { 
    static void foo() 
    { 
     std::cout << "I can not :(" << std::endl; 
    }   
    }; 

int main() 
{ 
    SubdataUser<basedata1>::foo(); 
    return 0; 
} 

不幸的是,据我所知,你不能因为如果Member不存在,编译失败有一个模板hasMember<Type,Member>::value

但你可能会喜欢这种类型的解决方案

#include <type_traits> 
#include <iostream> 

struct basedata1 
{ 
    struct Subdata1 {}; 
    struct Subdata2 {}; 
    struct Subdata3 {}; 
}; 

struct basedata2 
{ 
    struct Subdata1 {}; 
    //struct Subdata2 {}; 
    struct Subdata3 {}; 
}; 

template <class...> 
    struct Require 
    { 
    enum { value = true }; 
    }; 

template <class T, bool = true> 
    struct Impl 
    { 
    static void foo() 
    { 
     std::cout << "At least one of the members required is not available :(" << std::endl; 
    }   
    }; 

template <class T> 
    struct Impl<T, Require< typename T::Subdata1, 
          typename T::Subdata2, 
          typename T::Subdata3 >::value > 
    { 
    static void foo() 
    { 
     std::cout << "All members are available :)" << std::endl; 

     typename T::Subdata2 my_var; 
    }   
    }; 


int main(int argc, char* argv[]) 
{ 
    Impl<basedata1>::foo(); 
    Impl<basedata2>::foo(); 
    return 0; 
} 

我希望这有助于

+0

谢谢。这看起来好像会起作用。如果baseData和subData都是不同的设置,您是否有设置方法,以便可以设置baseA :: subBaseA和baseDataB :: subBaseB,还是必须分别明确地检查每一个? – sabbahillel 2015-02-23 22:54:58

+0

我看到这给出了显式Subdata作为泛型类T的成员的结果。但是,如何设置它以获取Subdata作为模板成员。也就是说,membeA,memberB,memberC需要检查和处理完成。如果有错误结果,我如何在主代码中设置电话来实际执行检查? – sabbahillel 2015-02-24 22:30:03

+0

我已经添加了另一个解决方案。你不能写一个模板'hasMember :: value',因为只有一个模板参数替换可以失败而没有错误。如果类型明确写入并且不存在,则编译失败。 – 2015-02-25 17:28:37