- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
根据 this stackoverflow 中的问题/答案,无法在 cython 中直接重写 C++ 嵌套 typedef。我遇到了这样的问题,我不知道哪种方法是正确/最佳的。
让我更具体地举个例子。下面,您可以找到两个 C++ 文件(一个 header.h 和一个 .cpp)和两个对应的 cython 文件(一个 .pxd 和一个 .pyx)的内容。在名为 cpp_graph.h
的 C++ 头文件中,您可以看到嵌套的 typedef 声明;例如,对应于 Graph::iterator::nn_iterator
。 我不知道如何在相应的 graph.pxd
文件中公开它。 或者,换句话说,我不知道什么是“官方”或“标准”的方式来做到这一点。
一些相关信息。如果您检查 STL 的 cython 包装器,您可以找到嵌套的 typedef。例如here在 utility.pxd
或 here 中在 vector.pxd
文件中。但是,ctypedef
的那些嵌套用法仅用于模板声明。 嵌套的 typedef 是否仅适用于 cython 中的模板声明?
C++ 头文件:
// file : cpp_graph.h
#ifndef Included_cpp_graph
#define Included_cpp_graph
#include <cassert>
#include <cstddef>
#include <set>
#include <map>
#include <iostream>
#include <string>
#include <sstream>
#include "to_string_patch.h"
#ifndef Defined_bint
#define Defined_bint
typedef int bint;
#endif
class Graph {
public:
typedef std::set< int > t_nn;
typedef std::set< int >::iterator nn_iterator;
typedef std::map< int , t_nn > t_node_to_nn;
class iterator
{
// To iterate over nodes.
friend class Graph;
public:
typedef iterator self_type;
typedef int value_type;
typedef int & reference;
typedef int * pointer;
typedef t_node_to_nn::iterator map_iterator;
typedef std::forward_iterator_tag iterator_category;
iterator( map_iterator map_it ) : _map_it( map_it ) { }
self_type operator++() { _map_it++; return *this; } // PREFIX
self_type operator++(int junk) { self_type i = *this; _map_it++; return i; } // POSTFIX
value_type operator*() { return ( * _map_it ).first; } // Return the index "i"
Graph::t_nn * operator->() { return & ( * _map_it ).second; } // Return a pointer to the contained t_nn.
bool operator==( const self_type & rhs ) { return _map_it == rhs._map_it; }
bool operator!=( const self_type & rhs ) { return _map_it != rhs._map_it; }
private:
map_iterator _map_it;
};
class const_iterator
{
friend class Vertex;
public:
typedef const_iterator self_type;
typedef int value_type;
typedef int & reference;
typedef int * pointer;
typedef t_node_to_nn::iterator map_iterator;
typedef std::forward_iterator_tag iterator_category;
const_iterator( map_iterator map_it ) : _map_it( map_it ) { }
self_type operator++() { _map_it++; return *this; } // PREFIX
self_type operator++(int junk) { self_type i = *this; _map_it++; return i; } // POSTFIX
const value_type operator*() { return ( * _map_it ).first; } // Return the index "i"
const Graph::t_nn * operator->() { return & ( * _map_it ).second; } // Return a pointer to the contained t_nn.
bool operator==( const self_type& rhs ) { return _map_it == rhs._map_it; }
bool operator!=( const self_type& rhs ) { return _map_it != rhs._map_it; }
private:
map_iterator _map_it;
};
iterator begin() { _node_to_nn.begin(); }
iterator end() { _node_to_nn.end(); }
const_iterator begin() const { _node_to_nn.begin(); }
const_iterator end() const { _node_to_nn.end(); }
nn_iterator nn_begin( int i ) { assert( has_node( i ) ); return _node_to_nn[ i ].begin(); }
nn_iterator nn_end( int i ) { assert( has_node( i ) ); return _node_to_nn[ i ].end(); }
Graph() : _num_links( 0 ) {}
~Graph() { _node_to_nn.clear(); _num_links = 0; }
Graph & subgraph( std::set< int > & nodes ) {
Graph * S = new Graph();
for ( std::set< int >::iterator n_it = nodes.begin() ; n_it != nodes.end() ; n_it++ ) {
int i = ( * n_it );
assert( has_node( i ) );
for ( nn_iterator j_it = nn_begin( i ) ; j_it != nn_end( i ) ; j_it++ ) {
int j = ( * j_it );
if ( nodes.count( j ) > 0 ) { S -> add_link( i , j ); }
}
}
return ( * S );
}
int num_nodes() { return _node_to_nn.size(); }
int num_links() { return _num_links; }
int degree( int i ) { return _node_to_nn[ i ].size(); }
double avrg_degree() { return ( ( double ) 2 * num_nodes() ) / ( ( double ) _num_links ); }
bool has_node( int i ) { return _node_to_nn.count( i ) > 0; }
bool has_nn( int i , int j ) {
if ( has_node( i ) ) { return _node_to_nn[ i ].count( j ) > 0; }
return false;
}
bool has_link( int i , int j ) { return has_nn( i , j ); }
void add_node( int i ) { _node_to_nn[ i ].count( 0 ); } // Trick...
void add_link( int i , int j ) {
if ( has_link( i , j ) ) { return; }
_node_to_nn[ i ].insert( j );
_node_to_nn[ j ].insert( i );
_num_links += 1;
}
void del_link( int i , int j ) {
if ( has_link( i , j ) ) {
_node_to_nn[ i ].erase( j );
_node_to_nn[ j ].erase( i );
_num_links -= 1;
}
}
void del_node( int i ) {
iterator i_it = _node_to_nn.find( i );
for( nn_iterator j_it = i_it -> begin() ; j_it != i_it -> end() ; j_it++ ) { del_link( i , ( * j_it ) ); }
_node_to_nn.erase( i_it._map_it );
}
void clear_node( int i ) { del_node( i ); add_node( i ); } // Trick...
private:
t_node_to_nn _node_to_nn;
int _num_links;
};
std::ostream& operator<<( std::ostream& os , Graph & G );
typedef Graph::t_nn Graph_t_nn
typedef
#endif // Included_cpp_graph
C++ .cpp 文件:
// cpp_graph.cpp
#include <cassert>
#include <cstddef>
#include <set>
#include <map>
#include <iostream>
#include <string>
#include <sstream>
#include "to_string_patch.h"
#include "cpp_graph.h"
std::ostream& operator<<( std::ostream& os , Graph & G ) {
os << "Graph{";
// Print nodes.
for ( Graph::iterator i_it = G.begin() ; i_it != G.end() ; i_it++ ) {
int i = ( * i_it );
os << " " << patch::to_string( i );
}
os << " |";
// Print edges.
for ( Graph::iterator i_it = G.begin() ; i_it != G.end() ; i_it++ ) {
int i = ( * i_it );
for ( Graph::nn_iterator j_it = G.nn_begin( i ) ; j_it != G.nn_end( i ) ; j_it++ ) {
int j = ( * j_it );
if ( i < j ) { os << " " + patch::to_string( i ) << ":" << patch::to_string( j ); }
}
}
os << " }"; // << std::endl;
return os;
}
// === For testing purposes ===.
/*
int main() {
Graph G;
G.add_link( 1 , 2 );
G.add_link( 1 , 3 );
G.add_link( 2 , 3 );
G.add_link( 3 , 4 );
G.add_link( 4 , 5 );
G.add_link( 4 , 6 );
G.add_link( 5 , 6 );
std::cout << G << std::endl;
G.del_link( 3 , 4 );
std::cout << G << std::endl;
G.del_node( 3 );
std::cout << G << std::endl;
G.clear_node( 2 );
std::cout << G << std::endl;
G.add_link( 100 , 101 );
std::cout << G << std::endl;
std::cout << "N = " << G.num_nodes() << " M = " << G.num_links() << std::endl;
}
*/
cython .pxd 文件:
# file : graph.pxd
# === Cython cimports ===
from libcpp cimport bool
from libcpp.set cimport set as cset
from libcpp.map cimport map as cmap
from cython.operator cimport dereference as deref, preincrement as inc
# === Exposing the C++ Graph class ===
cdef extern from "cpp_graph.h":
cdef cppclass Graph:
#public:
ctypedef cset[ int ] t_nn
ctypedef cset[ int ].iterator nn_iterator
ctypedef cmap[ int , t_nn ] t_node_to_nn
cppclass iterator:
#friend class Graph;
#public:
typedef iterator self_type
typedef int value_type
typedef int & reference
typedef int * pointer
typedef t_node_to_nn::iterator map_iterator
typedef std::forward_iterator_tag iterator_category
iterator( map_iterator map_it )
self_type operator++()
self_type operator++(int junk)
value_type operator*()
Graph::t_nn * operator->()
bool operator==( const self_type & rhs )
bool operator!=( const self_type & rhs )
#private:
# map_iterator _map_it;
cppclass const_iterator:
#friend class Vertex;
#public:
typedef const_iterator self_type
typedef int value_type
typedef int & reference
typedef int * pointer
typedef t_node_to_nn::iterator map_iterator
typedef std::forward_iterator_tag iterator_category
const_iterator( map_iterator map_it )
self_type operator++()
self_type operator++(int junk)
const value_type operator*()
const Graph::t_nn * operator->()
bool operator==( const self_type& rhs )
bool operator!=( const self_type& rhs )
#private:
# map_iterator _map_it;
iterator begin()
iterator end()
const_iterator begin() const
const_iterator end() const
nn_iterator nn_begin( int i )
nn_iterator nn_end( int i )
Graph()
~Graph()
Graph & subgraph( std::set< int > & nodes )
int num_nodes()
int num_links()
int degree( int i )
double avrg_degree()
bool has_node( int i )
bool has_nn( int i , int j )
bool has_link( int i , int j )
void add_node( int i )
void add_link( int i , int j )
void del_link( int i , int j )
void del_node( int i )
void clear_node( int i )
#private:
#t_node_to_nn _node_to_nn;
#int _num_links;
std::ostream& operator<<( std::ostream& os , Graph & G )
# === Python Wrapper for the C++ Graph class ===
cdef class PyGraph:
# === Data-members ===
# Pointer to a C++ Graph object.
cdef Graph * _c_graph
# === Function-members ===
# @ graph.pyx
和 cython .pyx 文件:
# file : graph.pyx
# === Cython cimports ===
from libcpp cimport bool
from libcpp.set cimport set as cset
from libcpp.map cimport map as cmap
from cython.operator cimport dereference as deref, preincrement as inc
# === Ctypedefs for Graph class ===
# @ graph.pxd
# === Exposing the C++ Graph class ===
cdef extern from "cpp_graph2.h":
cdef cppclass Graph:
#public:
ctypedef cset[ int ] t_nn
ctypedef cset[ int ].iterator nn_iterator
ctypedef cmap[ int , t_nn ] t_node_to_nn
cppclass iterator:
#friend class Graph;
#public:
typedef iterator self_type
typedef int value_type
typedef int & reference
typedef int * pointer
typedef t_node_to_nn::iterator map_iterator
typedef std::forward_iterator_tag iterator_category
iterator( map_iterator map_it )
self_type operator++()
self_type operator++(int junk)
value_type operator*()
Graph::t_nn * operator->()
bool operator==( const self_type & rhs )
bool operator!=( const self_type & rhs )
#private:
# map_iterator _map_it;
cppclass const_iterator:
#friend class Vertex;
#public:
typedef const_iterator self_type
typedef int value_type
typedef int & reference
typedef int * pointer
typedef t_node_to_nn::iterator map_iterator
typedef std::forward_iterator_tag iterator_category
const_iterator( map_iterator map_it )
self_type operator++()
self_type operator++(int junk)
const value_type operator*()
const Graph::t_nn * operator->()
bool operator==( const self_type& rhs )
bool operator!=( const self_type& rhs )
#private:
# map_iterator _map_it;
iterator begin()
iterator end()
const_iterator begin() const
const_iterator end() const
nn_iterator nn_begin( int i )
nn_iterator nn_end( int i )
Graph()
~Graph()
Graph & subgraph( std::set< int > & nodes )
int num_nodes()
int num_links()
int degree( int i )
double avrg_degree()
bool has_node( int i )
bool has_nn( int i , int j )
bool has_link( int i , int j )
void add_node( int i )
void add_link( int i , int j )
void del_link( int i , int j )
void del_node( int i )
void clear_node( int i )
#private:
#t_node_to_nn _node_to_nn;
#int _num_links;
# === Python Wrapper for the C++ Graph class ===
cdef class PyGraph:
# === Data-members ===
# @ graph.pxd
# === Function-members ===
def __cinit__( self ):
self._c_graph = new Graph()
def __dealloc__( self ):
del self._c_graph
# TODO : implement the methods for adding and deleting nodes/links.
最后,当我尝试编译/构建它时,出现以下错误:
###########################################################
# setup build_ext...
###########################################################
Error compiling Cython file:
------------------------------------------------------------
...
# === Exposing the C++ Graph class ===
cdef extern from "cpp_graph2.h":
cdef cppclass Graph:
#public:
ctypedef cset[ int ] t_nn
^
------------------------------------------------------------
ExcessDegreeModel/graph.pxd:51:8: Expected an identifier, found 'ctypedef'
...
最佳答案
我已经使用 namespace
关键字获得嵌套定义,指定嵌套声明。就像,如果你有名为 mystuff.hpp
的 C++ header 中的以下内容:
namespace MyStuff {
struct Outer {
struct Inner {
int value;
};
Inner member;
};
}
……你可以像这样对这些结构进行 encython:
cdef extern from "mystuff.hpp" namespace "MyStuff::Outer":
cppclass Inner:
int value
cdef extern from "mystuff.hpp" namespace "MyStuff":
cppclass Outer:
Inner member
…如果你真的把 C++ 领域的所有东西都包裹在一个命名空间中,它读起来会更连贯,如所写的那样(否则第二个 cdef
在其声明中没有 namespace
,在我看来,这看起来更奇怪)。
我有许多现实世界中当前正在使用的示例:one such example is here , another one is here .
关于c++ - 赛通 : exposing C++ classes with nested typedef (s),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39598499/
我想“创建”一个类型“my_type”,它是一个 std_logic_vector(...),就像这个 C/VHDL 假代码: typedef std_logic_vector(CONSTANT do
这个问题不太可能帮助任何 future 的访问者;它只与一个小的地理区域、一个特定的时间点或一个非常狭窄的情况有关,这些情况并不普遍适用于互联网的全局受众。为了帮助使这个问题更广泛地适用,visit
我已阅读说明,我明白它是一个函数类型别名。 typedef 或函数类型别名为函数类型提供一个名称,您可以在声明字段和返回类型时使用该名称。当将函数类型分配给变量时,typedef 会保留类型信息。 h
Vala 是否有能力做一些类似于 C 中的 typedef 或 D 中的 alias 的事情?我检查了它的零星文档,但找不到与此相关的任何内容。 最佳答案 不是 typedef 本身,但您可以扩展大多
我对这段代码有一些问题: typedef struct Product { char product_code[5]; int sells; int sells_quantit
我对书中的代码有疑问: const int SQUARE_ARRAY_SIZE = 4; const int SQUARE_INFO_SIZE = 4; typedef Square SquareAr
typedef经常像这样工作:typedef .但是函数指针的 typedef 似乎有不同的结构:typedef int (*fn)(char *, char *); - 没有类型别名,只有一个函
我被分配去处理一些代码,但我事先得到了一部分。它包括这部分代码: typedef int ElementType; struct Node; typedef struct Node *PtrToNod
我正在尝试创建通用容器包装器。 template class ContainerWrapper { public: using allocator_type = typename type::al
抱歉,标题太长了。 我在类列表中有一个 typedef: template class List { // Think of a class Iter_ with ListElem *pCu
我想制作一个 typedef,它依赖于模板参数中 typedef 的存在: struct foo { using MyType = int; }; template struct bar {
出于教育目的,我正在查看 Eigen 源代码。我注意到对于每个具体类模板 X在层次结构中,有一个 internal::traits定义。一个典型的例子可以在 Matrix.h 中找到: namespa
假设我有三个文件 //first.h typedef typename std::map MapVertexVd_t; //the graph class and ... //other useful
如果我需要 Swift 中的自定义类型,我可以 typedef,我该怎么做? (类似于闭包语法 typedef) 最佳答案 关键字typealias用于代替typedef: typealias Cus
由于标题可能看起来很困惑,让我举个例子: typedef bool foo[2]; typedef foo bar[4]; bar what_am_i; 所以,我认为 what_am_i 是 [4][
我想声明一个 typedef,像这样: 指向另一个 typedef 的任何数组的指针。 例如: 类型定义 1: typedef struct { int a; }structA_t1; 类型定
要将 my_int 声明为 int 的类型别名,我们可以这样写: typedef int my_int; // (1) 奇怪的是,以下内容似乎也定义了 int 别名: int typedef my
如何在其他 typedef struct 中声明 typedef struct? typedef struct { char* type; char* destination;
我正在尝试将 malloc'd ptr 保存在全局 ptr 中,以便我可以在另一个函数中使用它。理想情况下,我希望在全局范围内有一个更智能的数据结构,但现在我只是想让全局 ptr 工作。 在我的 lw
MachineState machine; ControlSignals theControls = machine.control_signals; //Why is this giving an
我是一名优秀的程序员,十分优秀!