Back to Projects
viper_

viper_

A fun single-header library that makes C++ feel just like Python

Oct 2024 - May 2025 7 months

Tech Stack

C++Python

About viper_

viper_ is a single-header library for modern C++ that provides a similar workflow to Python. viper_ is NOT a Python interpreter or language binding. It simply uses real C++ syntax to emulate Python’s core features.

Goals

  1. Emulate the feeling of Python: Support the most fundamental Python features.

  2. Use only real C++ syntax: I started this project to challenge myself to work around the constraints of the language. I will use as many interesting or esoteric C++ features as it takes to make it work.

  3. Stay as close as possible to Python’s syntax: Python will never be valid C++, so the syntax can’t be exactly the same. However, when I must deviate from Python syntax, I will do so as minimally and consistently as possible.

  4. Seamless interoperability: Must be able to easily call upon viper_ functionality from C++ and vice versa without extra setup.

Restrictions

  1. No interpreting entire strings of Python: Doing so would defeat the entire point of using C++ syntax by any means necessary. However, short strings for individual things like variable/function names are allowed.

Why the underscore?

The reason viper_ has the underscore is because it was born with the creation of the operator ""_ (see the next section), after which the underscore became the default for syntax that had to deviate from Python.

Current Features

Variables

Variables are strongly, dynamically duck-typed

# Python
my_var = 10 # Declare
my_var = "Hello!" # Reassign
print(my_var) # Access
# >> Hello!

With viper_, add quotes around and an underscore after variable names (string literal operator ""_)

// C++
"my_var"_ = 10; // Declare
"my_var"_ = "Hello!"; // Reassign
print("my_var"_); // Access
// >> Hello!

Note that "Hello!" doesn’t have the underscore because it’s a regular string and not a variable name like "my_var"_ is.

Format Strings

Format strings allow you to easily insert variable values into text using their names

# Python
text = "World"
formatted = f"Hello, {text}!" # Refers to the variable called text
print(formatted)
# >> Hello, World!

With viper_, use the same f"" syntax:

// C++
"text"_ = "World";
"formatted"_ = f"Hello, {text}!"; // Refers to the variable called text
print("formatted"_);

Note that the ""_ is not necessary for variable names inside the format string

Functions

# Python
def not_equal_to(x, y):
    return x != y
result = not_equal_to(1, 2) # True

With viper_, still use def but wrap the function name in parenthesis and wrap the code in curly braces folled by a semicolon

// C++
def (not_equal_to)("x"_, "y"_) {
    return "x"_ != "y"_;
};
"result"_ = not_equal_to(1, 2); // True

The curly braces and semicolon {...};are required because viper_ functions are technically C++ lambda declarations. This was necessary because C++ functions can’t be declared inside other functions, so they needed to be actual C++ variables.

The () around the function name was the best way to hide the capture [] of the lambda which otherwise would’ve required the developer to specify their own capture which would’ve felt strange from both C++ and Python perspectives.

*args can be used to allow any number of positional arguments to be passed to a function

# Python
def not_equal_to(x, *args):
    for arg in args:
        if x == arg:
            return False
    return True
result = not_equal_to(1, 5, 3, 1) # False

With viper_, it works the same

# C++
def (not_equal_to)("x"_, *"args"_) {
    for ("arg"_ in "args"_)
        if ("x"_ == "arg"_)
            return False;
    return True;
};
"result"_ = not_equal_to(1, 5, 3, 1); // False

- End of Documentation -

In viper_ but currently undocumented here:

View All Projects