2009-10-13 17 views
2

我目前正在爲需要預編譯二進制/ DLL(它將是跨平臺)的產品設計一個面向公衆的C++ API。我希望API允許用戶使用我們支持的任何POD(如果適用),但基本要求是最大的靈活性和二進制兼容性。我正在做一些與CPLEX的API類似的東西(它是幾種靈感之一),但我認爲可能有更好的方式來指定類型信息,而不是它們的做法(關於IloInt,IloNum,IloAny,Ilo * Var等,請參閱link(希望)用於IloExtractable分支),而不會破壞二進制兼容性。我錯了嗎?我有一些想法,但我不記得它是什麼,或者它甚至能夠工作,我相信它類似於訪問者或裝飾者模式,但對於類型,有人可以請我就這個問題給我點啓發嗎?我已經拿到了GoF的設計模式書。面向公衆的API支持多種POD類型,同時最大化二進制兼容性的建議設計是什麼?

注意:這裏可能存在的任何語法錯誤都不是問題的一部分。什麼,我相信我能不能用

例子,其原因:

可能..但是這很可能使事情與表達式樹複雜。

template<typename ValueType> 
Constraint : public Expression; 

可能會影響未來的擴張。

IntConstraint : public Expression; 
LongConstraint : public Expression; 
DoubleConstraint : public Expression; 

其醜無比,可能會導致大量的微妙的問題。

union Value 
{ 
int AsInt, 
float AsFloat 
}; 
class Constraint : public Expression 
{ 
    public: 
    Value GetValue(Edge); 
    void SetValue(Value, Edge); 
    void SetUpper(Value, Vertex); 
    void SetLower(Value, Vertex); 
    ... 
}; 

編輯:爲響應的Mads Elvheim(和發現this link後)我現在意識到,我並不需要排除從我準備的模板,這是很好的,但我仍然相當不確定這是最好的想法 - 至少對於約束類(儘管它在概念上是合理的),原諒我沒有像我想象的那麼清晰。

爲了使我的API易於使用,我使用bnf定義了語法(這對我來說是比較新穎的)。這導致了表達式,約束和其他類的抽象語法樹,這些類將被包括在與約束相互作用中。因爲其他類將與Constraints進行交互,所以我寧願避免直接傳遞作爲munch類型的信息,直到「最後一分鐘」爲止。我覺得我可能會錯過一個抽象層次。

研究CPLEX給我的印象是,他們通過遵循數字域(整體和真實),線性方程表達式(當然)以及相應的可能性來建模他們的類型,這絕對有意義,嗯...

(顯然,我不能因爲我是一個新的用戶發佈多個鏈接。)

編輯2:作爲第一步,我已經決定在約束和表達類之間堅持一個ConstraintExpressionArgument所以我仍然可以在我的表達式樹中識別一個約束,而不需要知道它操作哪種類型是好的。

我可能忽略提及的另一個細節是,與在其中約束類本身無法使用的CPLEX中不同,我的約束類當前是可用的用戶類,但與在CPLEX中一樣,我也希望留出擴展空間(因此打字問題)...

無論如何,此刻我有

class ConstraintExpressionArgument : public Expression; 
template<typename ValueType> 
class Constraint : public ConstraintExpressionArgument; 
+0

let me paraphrase ..你想允許用戶設置約束,但是允許傳遞給約束的值是任何POD,比如int或者float嗎? 他們能夠同時混合搭配這些限制嗎? POD數據類型的集合相當固定..你真的需要在那個方向上的可擴展性嗎? –

+0

對,是的,他們可以混合搭配。 我可以只提供長時間的值,因爲cplex使用IloInt,但因爲浮點數不能從用戶選擇中排除,所以我正在尋找提供使用多種類型選項的最無縫方式。 – Geoff

+0

鏈接[1]在這裏:http://www.mat.uc.pt/~jsoares/teaching/software/cplex/doc/html/refconcert/html/graph.html – Geoff

回答

0

對,我想我有我需要的東西,至少現在。

上面提到的

class ConstraintExpressionArgument : public Expression; 
template<typename ValueType> 
class Constraint : public ConstraintExpressionArgument; 

讓我在正確的軌道上,從約束岬分離型。

2

大多數系統相當於提供了一個<types.h><inttypes.h>標頭,您可以使用類型定義,如果準確的範圍或位的數目是非常重要的。我沒有看到在繼承問題上拋出繼承的好理由。如果指定的類型或模板類型與要求不匹配,您還可以使用std::numeric_limits和Boost的BOOST_STATIC_ASSERT()宏來生成有意義的編譯時斷言。要求可能是整數VS浮動,範圍,最小表示值,精度等。例如:

#include <limits> 
#include <inttypes.h> 
#include <boost/static_assert.hpp> 

template<class T, int bits> T Add(const T& a, const T& b) 
{ 
    BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer ); 
    BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_signed  ); 
    BOOST_STATIC_ASSERT(std::numeric_limits<T>::digits == bits); 

    return a + b; 
} 

如果的std :: numeric_limits沒有所有的類型,使用模板特延長並加以實施。

+0

我在實施中使用Boost,但寧願避免在公共(read:user)API中包含對Boost的依賴。 – Geoff