2013-07-29 32 views
3

我一直在嘗試使用C++ 11通用引用和一些類中的完美轉發,這些類也需要使用Boost.Python從Python進行訪問。我有可用的代碼,但它需要在課堂外部有一些醜陋的模板專門化。有沒有人以更優雅的方式解決這個問題?有沒有人對改進下面的代碼有任何建議?Boost.python通用參考/完美轉發?

#include <boost/python.hpp> 
#include <string> 

using namespace boost::python; 

struct A { 
    A() : _a("initial") {} 

    template <typename T> 
    void set_a(T&& a) { _a = std::forward<T>(a); } 

    const std::string& get_a() const { return _a; } 

private: 
    std::string _a; 
}; 

// How can the following template member function specialization be avoided? 
template <> 
void A::set_a(const std::string& a) { _a = a; } 

BOOST_PYTHON_MODULE(example) 
{ 
    class_<A>("A") 
     .add_property("a", make_function(&A::get_a, return_value_policy<copy_const_reference>()), 
        &A::set_a<const std::string&>) // Can this be defined differently? 
    ; 
} 
+0

什麼你希望從完美轉發,以獲得在這種情況下?保存副本?您的專業化有效地完全避免了被調用的轉發功能。 – nijansen

+0

是的,我試圖避免從C++端不必要的構造臨時對象,並避免複製。在C++端,可以使用Rvalues,Lvalues和字符串文字調用set_a()端的等價物。性能在這些路徑中非常重要。從Python調用時,性能不在任何類型的性能路徑中,但需要訪問某些對象。示例代碼可能錯誤地暗示着我試圖從Python代碼中避免拷貝,但這不是我的意圖。 – jhand

回答

1

我今天嘗試了一些,發現答案其實很簡單。

下面是簡化代碼:就在add_property的SETR部分再次使用make_function()

#include <boost/python.hpp> 
#include <string> 

using namespace boost::python; 

struct A { 
    A() : _a("initial") {} 

    template <typename T> 
    void set_a(T&& a) { _a = std::forward<T>(a); } 

    const std::string& get_a() const { return _a; } 

private: 
    std::string _a; 
}; 

BOOST_PYTHON_MODULE(example) 
{ 
    class_<A>("A") 
     .add_property("value", 
        make_function(&A::get_a, return_value_policy<copy_const_reference>()), 
        make_function(&A::set_a<const std::string&>) 
    ); 
}