【问题标题】:c++ conditional compilation based on member presence [duplicate]基于成员存在的c ++条件编译[重复]
【发布时间】:2012-09-25 15:22:06
【问题描述】:

可能重复:
Is it possible to write a C++ template to check for a function's existence?

在 JavaScript 等语言中,您可以检查属性是否存在

// javascript
if( object['property'] ) // do something

在 C++ 中,我想根据 T 类型是否具有特定属性来条件编译。这可能吗?

template <typename T>
class IntFoo
{
  T container ;
public:
  void add( int val )
  {
    // This doesn't work, but it shows what I'm trying to do.
    // if the container has a .push_front method/member, use it,
    // otherwise, use a .push_back method.
    #ifdef container.push_front
    container.push_front( val ) ;
    #else
    container.push_back( val ) ;
    #endif
  }

  void print()
  {
    for( typename T::iterator iter = container.begin() ; iter != container.end() ; ++iter )
      printf( "%d ", *iter ) ;

    puts( "\n--end" ) ;
  }
} ;

int main()
{
  // what ends up happening is 
  // these 2 have the same result (500, 200 --end).
  IntFoo< vector<int> > intfoo;
  intfoo.add( 500 ) ;
  intfoo.add( 200 ) ;
  intfoo.print() ;

  // expected that the LIST has (200, 500 --end)
  IntFoo< list<int> > listfoo ;
  listfoo.add( 500 ) ;
  listfoo.add( 200 ) ; // it always calls .push_back

  listfoo.print();
}

【问题讨论】:

  • 请看This Question
  • 哇! “替换失败不是错误”(SFINAE)!
  • 您可以编写一个特征来检查成员函数的存在(至少在 C++11 中)。 pretty printer 代码包含 begin() 成员函数的特征示例。

标签: c++ templates


【解决方案1】:

以下示例演示了一种可以使用的技术(在 C++11 中,使用 SFINAE for expressions):

typedef char no;
typedef no (&yes)[2];

no detect_push_front( ... );

template < class C >
auto detect_push_front( C &c ) -> typename std::conditional< false, decltype( c.push_front( std::declval< typename C::value_type >() ) ), yes >::type;

template < class C >
struct has_push_front : std::integral_constant< bool, sizeof( detect_push_front( std::declval< C & >() ) ) == sizeof( yes ) > {};

template < class C >
void add( C &c, typename C::value_type v, std::true_type )
{
    c.push_front( v );
}

template < class C >
void add( C &c, typename C::value_type v, std::false_type )
{
    c.push_back( v );
}

template < class C >
void add( C &c, typename C::value_type v )
{
    add( c, v, has_push_front< C >() );
}

int main()
{
    std::vector< int > v;
    add( v, 0 );
    add( v, 1 );
    add( v, 2 );
    std::copy( v.begin(), v.end(), std::ostream_iterator< int >( std::cout, " " ) );
    std::cout << '\n';

    std::list< int > l;
    add( l, 0 );
    add( l, 1 );
    add( l, 2 );
    std::copy( l.begin(), l.end(), std::ostream_iterator< int >( std::cout, " " ) );
    std::cout << '\n';
}

输出:

0 1 2
2 1 0

【讨论】:

  • 您可以添加此技术的名称以提高答案的质量。
  • 非常好。描述 SFINAE 的其他示例实际上涉及 runtime 检查,但这是编译时重载解决方案。
  • 赞成! - @bobobobo:哪些? SFINAE 通常是编译时的东西,因为它通常与重载决议有关。 (编辑:我意识到我在第一个单词中的错字,但发现它很有趣,我只是不纠正它)
  • This wikibooks example 有一个运行时检查(可能会被优化,但它仍然是一个if 语句)
【解决方案2】:

据我所知,在 C++ 中实现“条件编译”的唯一方法是使用预处理器指令,例如 ifdefifndef。我不存在任何其他技术。

【讨论】:

    【解决方案3】:

    你不能这样做,但你可以有类似的东西

    template<T,TT> void push_there(T& c,T& i) { c.push_back(i); }
    

    以及具有push_front 的容器类型的部分特化。或者反过来。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-08-25
      • 2011-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-28
      • 1970-01-01
      相关资源
      最近更新 更多