Qual é o design recomendado para as APIs voltadas para o público para suportar vários tipos de vagens e maximizar a compatibilidade binária?

StackOverflow https://stackoverflow.com/questions/1563491

Pergunta

Atualmente, estou projetando uma API C ++ voltada para um produto que exigirá uma binária/DLL pré-compilada (será uma plataforma cruzada). Gostaria que a API permita que o usuário use qualquer POD que suporte (onde aplicável), no entanto, os requisitos básicos são a máxima flexibilidade e compatibilidade binária. Estou fazendo algo um pouco semelhante à API da CPLEX (é uma das várias inspirações), mas acho que há uma maneira melhor de especificar informações do tipo do que como elas fizeram (com relação a ILoint, ilonum, iloany, ilo* Var, etc., veja link (espero) para o ramo iloextractável) sem mexer com compatibilidade binária. Estou errado? Eu tenho algo em mente, mas não me lembro do que é ou se funcionará, acredito que se assemelha a algo como os padrões de visitante ou decorador, mas para tipos, alguém poderia me esclarecer sobre o assunto? Eu tenho meu livro de padrões de design do GoF na minha frente.

Nota: Quaisquer erros de sintaxe que existam aqui não fazem parte do problema em questão.

Exemplos do que acredito que não posso usar e o motivo:

Possivelmente .. mas é provável que isso complique as coisas com a árvore de expressão.

template<typename ValueType>
Constraint : public Expression;

Provavelmente afetará a expansão futura.

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

Feio como pecado, pode causar muitos problemas sutis.

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

Editar: em resposta a Mads Elvheim (e depois de encontrar esse link) Agora percebo que não preciso excluir modelos de minhas possibilidades, o que é bom, mas ainda não tenho certeza de que é a melhor ideia - pelo menos para a aula de restrições (mesmo que seja conceitualmente sólida), perdoe -me por não ser Tão claro quanto eu pensava.

Para facilitar o uso da minha API, defini a gramática usando o BNF (o que é bastante novo para mim). Isso levou a uma árvore de sintaxe abstrata para expressão, restrições e outras classes que serão incluídas que interagem com restrições. Como outras classes estarão interagindo com as restrições, eu preferiria evitar a passagem do tipo mais informações do tipo Munch até "o último minuto", por assim dizer. Sinto que posso estar perdendo um nível de abstração.

Estudar o CPLEX me dá a impressão de que eles modelaram seus tipos seguindo os domínios dos números (inteiros e reais), expressão linear de equação (é claro) e o que deve ser possível, o que absolutamente faz sentido, hmm ...

(Aparentemente, não posso postar mais de um link, pois sou um novo usuário.)

Edit 2: Como primeiro passo, decidi colocar um ConstraintExpressionArgument Entre as classes de restrição e expressão para que eu ainda possa identificar uma restrição na minha árvore de expressão sem estar ciente do tipo que ela manipula que é boa.

Outro detalhe que posso ter deixado de mencionar foi que, diferentemente do CPLEX, onde a classe de restrição é inutilizável por si só, minha classe de restrição é atualmente uma classe de usuário utilizável, mas, como no CPLEX, também quero deixar espaço para expansão (portanto, o problema de digitação). ..

Enfim, no momento eu tenho o equivalente a

class ConstraintExpressionArgument : public Expression;
template<typename ValueType>
class Constraint : public ConstraintExpressionArgument;
Foi útil?

Solução 2

Certo, acho que tenho o que preciso, pelo menos por enquanto.

O que foi mencionado acima

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

Consegui-me no caminho certo para separar o tipo de restrição.

Outras dicas

A maioria dos sistemas fornece um <types.h> ou <inttypes.h> Cabeçalho com definições de tipo que você pode usar, se o intervalo exato ou o número de bits for importante. Não vejo um bom motivo para apresentar herança no problema. Você também pode usar std::numeric_limits junto com o Boost's BOOST_STATIC_ASSERT() Macro para gerar as afirmações significativas de tempo de compilação, se um tipo ou tipo de modelo especificado não corresponder a um requisito. O requisito pode ser inteiro versus flutuação, alcance, valor mínimo representável, precisão etc. por exemplo:

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

Se o STD :: numeric_limits não tiver todos os seus tipos, use a especialização do modelo para estendê -los e implementá -los.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top