Skip to content

Commit 79618ce

Browse files
committed
Add indexed identifier support to smt function factoryt
This is implemented using sfinae to detect if the supplied `functiont` has an `indices` member function or not, so that it is unneccessary to add an `indices` member function which returns the empty collections of indicies for the cases where `function` needs a simple (non indexed) identifier. `type_traits.h` is in `solvers/smt2_incremental/` because this is the only part of the codebase where it is currently used and keeping it here means the PR with this commit should need fewer code reviewer approvals.
1 parent d90f98c commit 79618ce

File tree

2 files changed

+79
-1
lines changed

2 files changed

+79
-1
lines changed

src/solvers/smt2_incremental/smt_terms.h

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77

88
#include <solvers/smt2_incremental/smt_index.h>
99
#include <solvers/smt2_incremental/smt_sorts.h>
10+
#include <solvers/smt2_incremental/type_traits.h>
1011

1112
#include <functional>
13+
#include <utility>
1214

1315
class BigInt;
1416
using mp_integer = BigInt;
@@ -136,6 +138,44 @@ class smt_function_application_termt : public smt_termt
136138
smt_identifier_termt function_identifier,
137139
std::vector<smt_termt> arguments);
138140

141+
// This is used to detect if \p functiont has an `indicies` member function.
142+
// It will resolve to std::true_type if it does or std::false type otherwise.
143+
template <class functiont, class = void>
144+
struct has_indicest : std::false_type
145+
{
146+
};
147+
148+
template <class functiont>
149+
struct has_indicest<
150+
functiont,
151+
void_t<decltype(std::declval<functiont>().indices())>> : std::true_type
152+
{
153+
};
154+
155+
/// Overload for when \p functiont does not have indices.
156+
template <class functiont>
157+
static std::vector<smt_indext>
158+
indices(const functiont &function, const std::false_type &has_indices)
159+
{
160+
return {};
161+
}
162+
163+
/// Overload for when \p functiont has indices member function.
164+
template <class functiont>
165+
static std::vector<smt_indext>
166+
indices(const functiont &function, const std::true_type &has_indices)
167+
{
168+
return function.indices();
169+
}
170+
171+
/// Returns `function.indices` if `functiont` has an `indices` member function
172+
/// or returns an empty collection otherwise.
173+
template <class functiont>
174+
static std::vector<smt_indext> indices(const functiont &function)
175+
{
176+
return indices(function, has_indicest<functiont>{});
177+
}
178+
139179
public:
140180
const smt_identifier_termt &function_identifier() const;
141181
std::vector<std::reference_wrapper<const smt_termt>> arguments() const;
@@ -160,7 +200,8 @@ class smt_function_application_termt : public smt_termt
160200
function.validate(arguments...);
161201
auto return_sort = function.return_sort(arguments...);
162202
return smt_function_application_termt{
163-
smt_identifier_termt{function.identifier(), std::move(return_sort)},
203+
smt_identifier_termt{
204+
function.identifier(), std::move(return_sort), indices(function)},
164205
{std::forward<argument_typest>(arguments)...}};
165206
}
166207
};
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Author: Diffblue Ltd.
2+
3+
/// \file
4+
/// Back ports of utilities available in the `<type_traits>` library for C++14
5+
/// or C++17 to C++11. These can be replaced with the standard library versions
6+
/// as and when we upgrade the version CBMC is compiled with.
7+
8+
#ifndef CPROVER_SOLVERS_SMT2_INCREMENTAL_TYPE_TRAITS_H
9+
#define CPROVER_SOLVERS_SMT2_INCREMENTAL_TYPE_TRAITS_H
10+
11+
#include <type_traits>
12+
13+
namespace detail // NOLINT
14+
{
15+
// Implementation detail of `void_t`.
16+
template <typename... typest>
17+
struct make_voidt
18+
{
19+
using type = void;
20+
};
21+
} // namespace detail
22+
23+
// The below definition is of a back-ported version of the C++17 STL
24+
// `std::void_t` template. This makes this particular template available when
25+
// compiling for the C++11 or C++14 standard versions. It will also compile
26+
// as-is when targeting the C++17 standard. The back-ported version is not added
27+
// to the `std` namespace as this would be undefined behaviour. However once we
28+
// permanently move to the new standard the below code should be removed
29+
// and `std::void_t` should be used directly, to avoid polluting the global
30+
// namespace. For example -
31+
// `void_t<decltype(foo.bar())>`
32+
// should be updated to -
33+
// `std::void_t<decltype(foo.bar())>`
34+
template <typename... typest>
35+
using void_t = typename detail::make_voidt<typest...>::type;
36+
37+
#endif // CPROVER_SOLVERS_SMT2_INCREMENTAL_TYPE_TRAITS_H

0 commit comments

Comments
 (0)