变量类型声明的C ++模板 [英] C++ template for variable type declaration

查看:118
本文介绍了变量类型声明的C ++模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些不同成员的类,所有类都有以下类型的操作。

I have a number of classes with differing members, all of which have operations of the following type

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

请注意,我要求如何设置通用模板来执行这些操作。我不能为每种类型的maindata和subinfo设置一个特殊情况。我还需要能够看到如何从我的主代码调用模板。我已经能够设置一个模板如果 maindata.subdata()存在,但是如果不存在,调用模板时仍然会收到编译失败。这是创建形式的模板

Note that I am asking how to set up generalized templates to perform these actions. I cannot set up a special case for each type of maindata and subinfo. I also need to be able to see how to call the template from my main code. I have been able to set up a template if maindata.subdata() exists, but keep getting a compilation failure on a call to the template if it does not exist. That is create the template of the form

perform_Push(maindata.subdata(), subinfo);

,因此无论maindata.subdata()是否存在,都可以编译。

so that it can be compiled whether or not maindata.subdata() exists or not.

我可以接受构建的模板,以便主代码可以显示

I could accept templates that build so that the main code can show

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

到目前为止,当调用的模板应该是void时,if中的代码不会被编译。

As of now, the code inside the if would not compile when the templates being called should just be void.

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

While ::basedata::Maindata is always defined, ::basedata::Subdata may or may not be defined depending on the release of libraries that my code is being build with. subdata is defined as a vector belonging to maindata which therefore has the push_back() operation defined. There are too many types of subData to create a separate template for each type as T::Subdata within a template in any case.

也就是说,如果subdata是唯一的case,我可以创建模板T的专业化为:: maindata :: subdata和一个通用模板T。

That is, if subdata was the only case, I could create a specialization of the template T as ::maindata::subdata and a generic Template T.

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

I do not have any control of the include files or library that for this so that I cannot create a #define of a variable to test with the pre-compiler. Is there a good way of setting up a template that would allow this to work? I could use a template that returns a boolean true (success) or false (no such definition) and call the alternate processing at run time. I would not need to have an alternate template.

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

Basically, I am asking how to apply SFINAE to this particular situation.

我已经设法找出了我需要做什么来设置基本模板

I have managed to figure out what I need to do to set up the basic template

如果我有最基本的操作

maindata.subdata().push_back(data)


b $ b

我可以定义一个形式的模板,

I can define a template of the form,

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

,呼叫

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

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

However, the problem would be how to set it up when maindata does not yet have a member subdata.

推荐答案

您可以使用此模板获取一个布尔值,告诉您是否存在成员类型 Subdata 在通用类型 T 中。只有当 T 是一个结构/类而不是一个命名空间时,它才能工作。

You can use this templates to obtain a boolean value that tell you if exist member type Subdata in a generic type T. This works only if T is a struct/class not a namespace.

#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;
}

但是你不能使用普通的if,因为编译器检查正确性所有的可能性。
你必须以类似的方式(很丑陋):

But you can't use a normal if because the compiler checks the correctness of all the possibilities. You have to act in a similar way (pretty ugly):

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;
}

据我所知,你不能有一个模板 hasMember< Type,Member> :: value 因为如果 Member

Unfortunately to my knowledge, you can not have a template hasMember<Type,Member>::value because if Member does not exist, compilation fails.

But you might like a solution of this type

$ c> #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
{
枚举{value = true};
};

template< class T,bool = true>
struct Impl
{
static void foo
{
std :: cout<< 至少有一个所需的成员不可用:(<<< std :: endl;
}
};

模板< class T>
struct Impl< T,Require< typename T :: Subdata1,
typename T :: Subdata2,
typename T :: Subdata3> :: value>
{
static void foo()
{
std :: cout<<所有成员都可用:)< std :: endl;

typename T :: Subdata2 my_var;
}
};


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

#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; }

我希望这有助于

这篇关于变量类型声明的C ++模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆