Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
42a776d
base data structures fot hook implementation.
NeaguGeorgiana23 Jul 7, 2026
e968609
fix linter
NeaguGeorgiana23 Jul 7, 2026
334ec2a
fix linter
NeaguGeorgiana23 Jul 7, 2026
f110e5c
Merge branch 'main' into define-hook-data-structures
NeaguGeorgiana23 Jul 7, 2026
5cc878b
Update BUILD file.
NeaguGeorgiana23 Jul 10, 2026
bd66430
Correct include guards.
NeaguGeorgiana23 Jul 10, 2026
5332610
feat: Add HookData class.
NeaguGeorgiana23 Jul 10, 2026
c8fc92d
fix linter
NeaguGeorgiana23 Jul 10, 2026
3f5f4de
fix linter
NeaguGeorgiana23 Jul 10, 2026
b0f3a15
fix linter
NeaguGeorgiana23 Jul 10, 2026
e9e8852
fix linter
NeaguGeorgiana23 Jul 10, 2026
e333df0
add HookContext structure.
NeaguGeorgiana23 Jul 13, 2026
c59de28
fix linter
NeaguGeorgiana23 Jul 13, 2026
45ca64a
fix linter
NeaguGeorgiana23 Jul 13, 2026
3b93d77
add Hooks class.
NeaguGeorgiana23 Jul 14, 2026
a4aa1c2
fix linter.
NeaguGeorgiana23 Jul 14, 2026
d7cd54a
fix linter.
NeaguGeorgiana23 Jul 14, 2026
d6ef2c6
fix linter.
NeaguGeorgiana23 Jul 14, 2026
a2f7fee
fix linter.
NeaguGeorgiana23 Jul 14, 2026
a91afca
appli agent suggestions.
NeaguGeorgiana23 Jul 14, 2026
c0482f7
Merge branch 'main' into hooks
NeaguGeorgiana23 Jul 14, 2026
a0ca155
Merge branch 'main' into hooks
NeaguGeorgiana23 Jul 14, 2026
06bd51c
Add EvaluationOpton struct.
NeaguGeorgiana23 Jul 15, 2026
b362223
fix linter.
NeaguGeorgiana23 Jul 15, 2026
6942c4e
update Provider class to allow getting hooks.
NeaguGeorgiana23 Jul 15, 2026
49bdc17
update all classes that inharit from FeatureProvider.
NeaguGeorgiana23 Jul 15, 2026
dab62a0
update BUILD files and imports.
NeaguGeorgiana23 Jul 15, 2026
ea6a463
update GlobalAPI with hook methods.
NeaguGeorgiana23 Jul 15, 2026
665914a
fix linter.
NeaguGeorgiana23 Jul 16, 2026
0bd0f58
fix linter.
NeaguGeorgiana23 Jul 16, 2026
153fc57
Merge branch 'main' of https://github.com/open-feature/cpp-sdk into u…
NeaguGeorgiana23 Aug 10, 2026
543edd0
Fix linter.
NeaguGeorgiana23 Aug 10, 2026
3e28c56
Update Clint API to support Hooks
NeaguGeorgiana23 Aug 10, 2026
0b6c84b
Overload functions to support EvaluationOptions.
NeaguGeorgiana23 Aug 10, 2026
bdbc5ca
fix linter.
NeaguGeorgiana23 Aug 10, 2026
408322e
fix tests
NeaguGeorgiana23 Aug 10, 2026
3f71061
Merge branch 'main' of https://github.com/open-feature/cpp-sdk into o…
NeaguGeorgiana23 Aug 11, 2026
3f148a2
Merge branch 'main' into overload_client_functions
NeaguGeorgiana23 Aug 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion openfeature/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ cc_library(
include_prefix = "openfeature",
deps = [
":evaluation_context",
":value"
":evaluation_options",
":value",
],
)

Expand Down
123 changes: 103 additions & 20 deletions openfeature/client_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,62 +30,141 @@ ProviderStatus ClientAPI::GetProviderStatus() {
}

bool ClientAPI::GetBooleanValue(std::string_view flag_key, bool default_value) {
return EvaluateBooleanFlag(flag_key, default_value, std::nullopt)->GetValue();
return EvaluateBooleanFlag(flag_key, default_value, std::nullopt,
std::nullopt)
->GetValue();
}

bool ClientAPI::GetBooleanValue(std::string_view flag_key, bool default_value,
const EvaluationContext& ctx) {
return EvaluateBooleanFlag(flag_key, default_value, ctx)->GetValue();
return EvaluateBooleanFlag(flag_key, default_value, ctx, std::nullopt)
->GetValue();
}

bool ClientAPI::GetBooleanValue(std::string_view flag_key, bool default_value,
const EvaluationOptions& options) {
return EvaluateBooleanFlag(flag_key, default_value, std::nullopt, options)
->GetValue();
}

bool ClientAPI::GetBooleanValue(std::string_view flag_key, bool default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) {
return EvaluateBooleanFlag(flag_key, default_value, ctx, options)->GetValue();
}

std::string ClientAPI::GetStringValue(std::string_view flag_key,
std::string_view default_value) {
return EvaluateStringFlag(flag_key, default_value, std::nullopt)->GetValue();
return EvaluateStringFlag(flag_key, default_value, std::nullopt, std::nullopt)
->GetValue();
}

std::string ClientAPI::GetStringValue(std::string_view flag_key,
std::string_view default_value,
const EvaluationContext& ctx) {
return EvaluateStringFlag(flag_key, default_value, ctx)->GetValue();
return EvaluateStringFlag(flag_key, default_value, ctx, std::nullopt)
->GetValue();
}

std::string ClientAPI::GetStringValue(std::string_view flag_key,
std::string_view default_value,
const EvaluationOptions& options) {
return EvaluateStringFlag(flag_key, default_value, std::nullopt, options)
->GetValue();
}

std::string ClientAPI::GetStringValue(std::string_view flag_key,
std::string_view default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) {
return EvaluateStringFlag(flag_key, default_value, ctx, options)->GetValue();
}

int64_t ClientAPI::GetIntegerValue(std::string_view flag_key,
int64_t default_value) {
return EvaluateIntegerFlag(flag_key, default_value, std::nullopt)->GetValue();
return EvaluateIntegerFlag(flag_key, default_value, std::nullopt,
std::nullopt)
->GetValue();
}

int64_t ClientAPI::GetIntegerValue(std::string_view flag_key,
int64_t default_value,
const EvaluationContext& ctx) {
return EvaluateIntegerFlag(flag_key, default_value, ctx)->GetValue();
return EvaluateIntegerFlag(flag_key, default_value, ctx, std::nullopt)
->GetValue();
}

int64_t ClientAPI::GetIntegerValue(std::string_view flag_key,
int64_t default_value,
const EvaluationOptions& options) {
return EvaluateIntegerFlag(flag_key, default_value, std::nullopt, options)
->GetValue();
}

int64_t ClientAPI::GetIntegerValue(std::string_view flag_key,
int64_t default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) {
return EvaluateIntegerFlag(flag_key, default_value, ctx, options)->GetValue();
}

double ClientAPI::GetDoubleValue(std::string_view flag_key,
double default_value) {
return EvaluateDoubleFlag(flag_key, default_value, std::nullopt)->GetValue();
return EvaluateDoubleFlag(flag_key, default_value, std::nullopt, std::nullopt)
->GetValue();
}

double ClientAPI::GetDoubleValue(std::string_view flag_key,
double default_value,
const EvaluationContext& ctx) {
return EvaluateDoubleFlag(flag_key, default_value, ctx)->GetValue();
return EvaluateDoubleFlag(flag_key, default_value, ctx, std::nullopt)
->GetValue();
}

double ClientAPI::GetDoubleValue(std::string_view flag_key,
double default_value,
const EvaluationOptions& options) {
return EvaluateDoubleFlag(flag_key, default_value, std::nullopt, options)
->GetValue();
}

double ClientAPI::GetDoubleValue(std::string_view flag_key,
double default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) {
return EvaluateDoubleFlag(flag_key, default_value, ctx, options)->GetValue();
}

Value ClientAPI::GetObjectValue(std::string_view flag_key,
Value default_value) {
return EvaluateObjectFlag(flag_key, default_value, std::nullopt)->GetValue();
return EvaluateObjectFlag(flag_key, default_value, std::nullopt, std::nullopt)
->GetValue();
}

Value ClientAPI::GetObjectValue(std::string_view flag_key, Value default_value,
const EvaluationContext& ctx) {
return EvaluateObjectFlag(flag_key, default_value, ctx)->GetValue();
return EvaluateObjectFlag(flag_key, default_value, ctx, std::nullopt)
->GetValue();
}

Value ClientAPI::GetObjectValue(std::string_view flag_key, Value default_value,
const EvaluationOptions& options) {
return EvaluateObjectFlag(flag_key, default_value, std::nullopt, options)
->GetValue();
}

Value ClientAPI::GetObjectValue(std::string_view flag_key, Value default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) {
return EvaluateObjectFlag(flag_key, default_value, ctx, options)->GetValue();
}

std::unique_ptr<BoolResolutionDetails> ClientAPI::EvaluateBooleanFlag(
std::string_view flag_key, bool default_value,
const std::optional<EvaluationContext>& ctx) {
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options) {
return this->EvaluateFlag<BoolResolutionDetails>(
default_value, ctx,
default_value, ctx, options,
[&](const std::shared_ptr<FeatureProvider>& provider,
const EvaluationContext& merged_ctx) {
return provider->GetBooleanEvaluation(flag_key, default_value,
Expand All @@ -95,10 +174,11 @@ std::unique_ptr<BoolResolutionDetails> ClientAPI::EvaluateBooleanFlag(

std::unique_ptr<StringResolutionDetails> ClientAPI::EvaluateStringFlag(
std::string_view flag_key, std::string_view default_value,
const std::optional<EvaluationContext>& ctx) {
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options) {
std::string default_str(default_value);
return this->EvaluateFlag<StringResolutionDetails>(
default_str, ctx,
default_str, ctx, options,
[&](const std::shared_ptr<FeatureProvider>& provider,
const EvaluationContext& merged_ctx) {
return provider->GetStringEvaluation(flag_key, default_value,
Expand All @@ -108,9 +188,10 @@ std::unique_ptr<StringResolutionDetails> ClientAPI::EvaluateStringFlag(

std::unique_ptr<IntResolutionDetails> ClientAPI::EvaluateIntegerFlag(
std::string_view flag_key, int64_t default_value,
const std::optional<EvaluationContext>& ctx) {
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options) {
return this->EvaluateFlag<IntResolutionDetails>(
default_value, ctx,
default_value, ctx, options,
[&](const std::shared_ptr<FeatureProvider>& provider,
const EvaluationContext& merged_ctx) {
return provider->GetIntegerEvaluation(flag_key, default_value,
Expand All @@ -120,9 +201,10 @@ std::unique_ptr<IntResolutionDetails> ClientAPI::EvaluateIntegerFlag(

std::unique_ptr<DoubleResolutionDetails> ClientAPI::EvaluateDoubleFlag(
std::string_view flag_key, double default_value,
const std::optional<EvaluationContext>& ctx) {
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options) {
return this->EvaluateFlag<DoubleResolutionDetails>(
default_value, ctx,
default_value, ctx, options,
[&](const std::shared_ptr<FeatureProvider>& provider,
const EvaluationContext& merged_ctx) {
return provider->GetDoubleEvaluation(flag_key, default_value,
Expand All @@ -132,9 +214,10 @@ std::unique_ptr<DoubleResolutionDetails> ClientAPI::EvaluateDoubleFlag(

std::unique_ptr<ObjectResolutionDetails> ClientAPI::EvaluateObjectFlag(
std::string_view flag_key, Value default_value,
const std::optional<EvaluationContext>& ctx) {
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options) {
return this->EvaluateFlag<ObjectResolutionDetails>(
default_value, ctx,
default_value, ctx, options,
[&](const std::shared_ptr<FeatureProvider>& provider,
const EvaluationContext& merged_ctx) {
return provider->GetObjectEvaluation(flag_key, default_value,
Expand Down
56 changes: 50 additions & 6 deletions openfeature/client_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,66 @@ class ClientAPI : public Client {
bool GetBooleanValue(std::string_view flag_key, bool default_value) override;
bool GetBooleanValue(std::string_view flag_key, bool default_value,
const EvaluationContext& ctx) override;
bool GetBooleanValue(std::string_view flag_key, bool default_value,
const EvaluationOptions& options) override;
bool GetBooleanValue(std::string_view flag_key, bool default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) override;

// Evaluate a string flag.
std::string GetStringValue(std::string_view flag_key,
std::string_view default_value) override;
std::string GetStringValue(std::string_view flag_key,
std::string_view default_value,
const EvaluationContext& ctx) override;
std::string GetStringValue(std::string_view flag_key,
std::string_view default_value,
const EvaluationOptions& options) override;
std::string GetStringValue(std::string_view flag_key,
std::string_view default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) override;

// Evaluate an integer flag.
int64_t GetIntegerValue(std::string_view flag_key,
int64_t default_value) override;
int64_t GetIntegerValue(std::string_view flag_key, int64_t default_value,
const EvaluationContext& ctx) override;
int64_t GetIntegerValue(std::string_view flag_key, int64_t default_value,
const EvaluationOptions& options) override;
int64_t GetIntegerValue(std::string_view flag_key, int64_t default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) override;

// Evaluate a double flag.
double GetDoubleValue(std::string_view flag_key,
double default_value) override;
double GetDoubleValue(std::string_view flag_key, double default_value,
const EvaluationContext& ctx) override;
double GetDoubleValue(std::string_view flag_key, double default_value,
const EvaluationOptions& options) override;
double GetDoubleValue(std::string_view flag_key, double default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) override;

// Evaluate an object flag.
Value GetObjectValue(std::string_view flag_key, Value default_value) override;
Value GetObjectValue(std::string_view flag_key, Value default_value,
const EvaluationContext& ctx) override;
Value GetObjectValue(std::string_view flag_key, Value default_value,
const EvaluationOptions& options) override;
Value GetObjectValue(std::string_view flag_key, Value default_value,
const EvaluationContext& ctx,
const EvaluationOptions& options) override;

// Adds one or more hooks to the client-level hook repository.
void AddHooks(std::vector<std::shared_ptr<GeneralHook>> hooks) override;

// Adds a single hook to the client-level hook repository.
void AddHook(std::shared_ptr<GeneralHook> hook) override;

// Retrieves all configured client-level hooks.
std::vector<std::shared_ptr<GeneralHook>> GetHooks() const override;
Comment on lines +102 to +109

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

ast-grep outline openfeature/client_api.h --match ClientAPI --view expanded
sed -n '95,120p' openfeature/client_api.h

Repository: open-feature/cpp-sdk

Length of output: 1413


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,185p' openfeature/client_api.h
printf '\nDuplicate declarations:\n'
python3 - <<'PY'
from pathlib import Path
import re

text = Path("openfeature/client_api.h").read_text()
patterns = [
    r'void AddHooks\(std::vector<std::shared_ptr<GeneralHook>> hooks\) override;',
    r'void AddHook\(std::shared_ptr<GeneralHook> hook\) override;',
    r'std::vector<std::shared_ptr<GeneralHook>> GetHooks\(\) const override;',
]
for pattern in patterns:
    matches = list(re.finditer(pattern, text))
    print(pattern, "count=", len(matches),
          "lines=", [text.count("\n", 0, m.start()) + 1 for m in matches])
PY

printf '\nAvailable C++ compiler:\n'
command -v c++ || true
command -v g++ || true

Repository: open-feature/cpp-sdk

Length of output: 8684


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '%s\n' 'struct Base { virtual void f() = 0; };' \
              'struct Derived : Base { void f() override; void f() override; };' \
              'int main() { return 0; }' |
  c++ -std=c++17 -fsyntax-only -x c++ -

printf 'standalone duplicate-member declaration accepted\n'

Repository: open-feature/cpp-sdk

Length of output: 260


🌐 Web query:

C++ standard duplicate identical member function declarations in the same class allowed or ill-formed

💡 Result:

In C++, declaring the exact same member function twice within the same class definition is generally ill-formed, as the C++ standard explicitly states that a member shall not be declared twice in the member-specification of a class [1][2]. However, this rule is subject to specific nuances and exceptions: 1. Overloading vs. Redeclaration: If you declare two member functions with the same name, they are not necessarily "duplicates." If their parameter-type-lists or cv-qualifiers differ in ways that allow for function overloading, the compiler treats them as separate overloads rather than a forbidden duplicate declaration [3][4]. The program only becomes ill-formed if the signatures are identical (or equivalent) in a way that does not constitute valid overloading [5][3]. 2. General Rule for Entities: Under the general rules for conflicting declarations in C++, two declarations in the same scope cannot reintroduce the same entity unless they are compatible (e.g., in the case of overloading) [5][6]. If two declarations for the same member function appear in the same class scope and have identical signatures, it is considered a redeclaration of the same entity and is ill-formed [5][3]. 3. Exceptions: The standard provides limited exceptions where a member may be redeclared. For example, nested classes or member class templates can be declared and then later defined [1][4]. Additionally, an enumeration can be introduced with an opaque-enum-declaration and later redeclared with an enum-specifier [2][4]. These exceptions do not apply to standard member functions. In summary, attempting to provide an identical declaration for a member function in the same class will cause a compiler error because it violates the restriction against declaring the same member multiple times [1][2]. If you intended to overload the function, you must ensure the signatures differ sufficiently according to C++ overload resolution rules [3][4].

Citations:


Remove the duplicate hook declarations.

ClientAPI declares AddHooks, AddHook, and GetHooks twice with identical signatures. This makes the class definition ill-formed and blocks compilation. Remove either declaration set.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@openfeature/client_api.h` around lines 102 - 109, Remove one duplicate
declaration set for AddHooks, AddHook, and GetHooks in ClientAPI, retaining
exactly one declaration of each method with its existing signatures and override
specifiers.


// Adds one or more hooks to the client-level hook repository.
void AddHooks(std::vector<std::shared_ptr<GeneralHook>> hooks) override;
Expand All @@ -80,34 +118,39 @@ class ClientAPI : public Client {
std::vector<std::shared_ptr<GeneralHook>> GetHooks() const override;

// TODO: Add methods for detailed flag evaluation.
// TODO: Overload method "GetBooleanValue" to accept "Evaluation Options".

private:
template <typename ResolutionDetailsType, typename ValueType,
typename ProviderCallable>
std::unique_ptr<ResolutionDetailsType> EvaluateFlag(
ValueType default_value, const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options,
ProviderCallable provider_call);

std::unique_ptr<BoolResolutionDetails> EvaluateBooleanFlag(
std::string_view flag_key, bool default_value,
const std::optional<EvaluationContext>& ctx);
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options = std::nullopt);

std::unique_ptr<StringResolutionDetails> EvaluateStringFlag(
std::string_view flag_key, std::string_view default_value,
const std::optional<EvaluationContext>& ctx);
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options = std::nullopt);

std::unique_ptr<IntResolutionDetails> EvaluateIntegerFlag(
std::string_view flag_key, int64_t default_value,
const std::optional<EvaluationContext>& ctx);
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options = std::nullopt);

std::unique_ptr<DoubleResolutionDetails> EvaluateDoubleFlag(
std::string_view flag_key, double default_value,
const std::optional<EvaluationContext>& ctx);
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options = std::nullopt);

std::unique_ptr<ObjectResolutionDetails> EvaluateObjectFlag(
std::string_view flag_key, Value default_value,
const std::optional<EvaluationContext>& ctx);
const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options = std::nullopt);

EvaluationContext MergeContexts(
const std::optional<EvaluationContext>& invocation_ctx);
Expand All @@ -124,6 +167,7 @@ template <typename ResolutionDetailsType, typename ValueType,
typename ProviderCallable>
std::unique_ptr<ResolutionDetailsType> ClientAPI::EvaluateFlag(
ValueType default_value, const std::optional<EvaluationContext>& ctx,
const std::optional<EvaluationOptions>& options,
ProviderCallable provider_call) {
std::shared_ptr<FeatureProviderStatusManager> manager =
provider_repository_.GetFeatureProviderStatusManager(domain_);
Expand Down
Loading
Loading