C++
std::real
overloaded function
address resolution
programming techniques

resolve address from overloaded function stdrealfloat

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Taking the address of an overloaded function in C plus plus can fail because the compiler cannot guess which overload you mean. This happens often with standard library overload sets such as std::real. The fix is to provide an explicit function pointer type or cast so overload resolution has one valid target.

Why Overload Address Resolution Fails

When you write &std::real, you refer to a set of candidate functions. Without expected type context, there is no unique match.

cpp
1#include <complex>
2
3int main() {
4    auto p = &std::real; // error: overloaded function
5}

The compiler needs extra type information to pick one overload.

Resolve with Explicit Function Pointer Type

One clean approach is declaring the exact pointer signature first.

cpp
1#include <complex>
2#include <iostream>
3
4int main() {
5    using RealFromComplexFloat = float (*)(const std::complex<float>&);
6    RealFromComplexFloat ptr = &std::real;
7
8    std::complex<float> z(3.5f, -2.0f);
9    std::cout << ptr(z) << "\n";
10}

The alias gives context, so the compiler selects the overload accepting std::complex<float>.

Resolve with static_cast

If you do not want a separate alias, cast inline to the intended signature.

cpp
1#include <complex>
2#include <iostream>
3
4int main() {
5    auto ptr = static_cast<float (*)(const std::complex<float>&)>(&std::real);
6
7    std::complex<float> z(7.0f, 1.5f);
8    std::cout << ptr(z) << "\n";
9}

static_cast is explicit and works well in local usage.

Overloads for Scalar Inputs

std::real has overloads that return scalar values for scalar inputs too. If you want the scalar version, choose that signature explicitly.

cpp
1#include <complex>
2#include <iostream>
3
4int main() {
5    auto ptr = static_cast<float (*)(float)>(&std::real);
6    std::cout << ptr(12.25f) << "\n";
7}

The important point is matching the exact function type you intend to call.

Using in Generic Code

Template-heavy code often stores function pointers for later invocation. Provide signature via template parameters to keep overload resolution deterministic.

cpp
1#include <complex>
2#include <iostream>
3
4template <typename Fn, typename Arg>
5void call_and_print(Fn fn, const Arg& arg) {
6    std::cout << fn(arg) << "\n";
7}
8
9int main() {
10    using Sig = double (*)(const std::complex<double>&);
11    Sig fn = &std::real;
12
13    std::complex<double> z(9.0, 4.0);
14    call_and_print(fn, z);
15}

If you rely only on auto without a signature hint, overload sets can become ambiguous quickly.

Alternative: Wrap in Lambda

A lambda wrapper is sometimes the simplest and most readable option.

cpp
1#include <complex>
2#include <iostream>
3
4int main() {
5    auto real_float = [](const std::complex<float>& z) {
6        return std::real(z);
7    };
8
9    std::complex<float> z(2.5f, 8.5f);
10    std::cout << real_float(z) << "\n";
11}

This avoids direct overload-address syntax and keeps intent obvious.

Compiler and Standard Library Notes

Different compilers may print different diagnostics for overload ambiguity, but the resolution strategy is the same. Give explicit type context. Also note that function overload availability can vary slightly by standard version and included headers, so always include the appropriate standard headers for the overload set you target.

In practice, most issues come from missing explicit signatures rather than library defects.

Practical Rule for Overload Pointers

When you need the address of any overloaded standard function, start by writing the exact target signature first and let that declaration drive selection. This approach scales beyond std::real to many overloaded algorithms and math helpers.

cpp
using Fn = long double (*)(const std::complex<long double>&);
Fn f = &std::real;

If this line compiles, overload resolution is complete and your intent is explicit to both compiler and future readers.

Common Pitfalls

  • Taking &std::real with no target type. Fix by declaring a function pointer type first.
  • Casting to the wrong signature. Fix by matching exact argument and return types.
  • Assuming scalar and complex overloads are interchangeable. Fix by choosing overload based on input type.
  • Using auto where overload context is required. Fix by adding type aliases or explicit casts.
  • Debugging compiler messages without reducing ambiguity. Fix by simplifying code to one explicit signature and rebuilding.

Summary

  • &std::real is ambiguous because it represents an overload set.
  • Overload address resolution needs explicit function type context.
  • Use type aliases or static_cast to choose the correct overload.
  • Lambda wrappers are a readable alternative in many codebases.
  • Explicit signatures prevent ambiguity in generic and template-heavy code.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.