nicolapiccinelli / libmpc

libmpc++ is a C++ header-only library to solve linear and non-linear MPC
https://altairlab.gitlab.io/optcontrol/libmpc/
MIT License
137 stars 21 forks source link

`error: non-type template parameters of class type only available` using Dockerfile setup #18

Closed pwintz closed 11 months ago

pwintz commented 11 months ago

I'm having trouble getting a C++ file to compile when I include any libmpc headers. Here's a MWE:

// A file named "test_libmpc.cpp"
#include <mpc/IComponent.hpp>

To compile, I'm running

g++ -c test_libmpc.cpp -I ~/libmpc-0.4.0/include/ -I /usr/include/eigen3/ -std=c++20

where ~/libmpc-0.4.0 is the path to libmpc and /usr/include/eigen3 is the path to the Eigen installation.

The error I get is as follows:

root@pwintz-2-in-1:~# g++ -c test_libmpc.cpp -I ~/libmpc-0.4.0/include/ -I /usr/include/eigen3/
In file included from test_libmpc.cpp:1:
/root/libmpc-0.4.0/include/mpc/IComponent.hpp:25:23: error: non-type template parameters of class type only available with '-std=c++20' or '-std=gnu++20'
   25 |     template <MPCSize sizer>
      |                       ^~~~~
/root/libmpc-0.4.0/include/mpc/IComponent.hpp:26:45: error: expected template-name before '<' token
   26 |     class IComponent : public IDimensionable<sizer>
      |                                             ^
/root/libmpc-0.4.0/include/mpc/IComponent.hpp:26:45: error: expected '{' before '<' token

My setup is based on the Dockerfile included in the libmpc repository modified to also download libmpc to my user directory (/root/libmpc-0.4.0). Here's my version of the Dockerfile:

FROM ubuntu:latest

ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /

##############################
# Core tools
##############################

RUN apt-get update -y -qq \
    && apt-get install -y -qq --no-install-recommends \
        apt-utils \
        lsb-release \
        build-essential \
        software-properties-common \
        ca-certificates \
        gpg-agent \
        wget \
        git \
        cmake \
        lcov \
        gcc \
        clang \
        clang-tidy \
        clang-format \
        libomp-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

##############################
# Non-root user Setup
##############################
ARG USERNAME=dev
RUN apt-get update -qq \
    && apt-get install -y --no-install-recommends \
        sudo \
        gosu \
    && rm -rf /var/lib/apt/lists/* \
    && useradd --create-home --home-dir /home/$USERNAME --shell /bin/bash --user-group --groups adm,sudo $USERNAME \
    && echo $USERNAME:$USERNAME | chpasswd \
    && echo $USERNAME ALL=\(ALL\) NOPASSWD:ALL >> /etc/sudoers \
    && touch home/$USERNAME/.sudo_as_admin_successful \
    && gosu $USERNAME mkdir -p /home/$USERNAME/.xdg_runtime_dir
ENV XDG_RUNTIME_DIR=/home/$USERNAME/.xdg_runtime_dir

##############################
# libMPC++
##############################
# Downloads and unzips lipmpc into the home directory.
RUN cd ~ && wget https://github.com/nicolapiccinelli/libmpc/archive/refs/tags/0.4.0.tar.gz \
    && tar -xzvf 0.4.0.tar.gz \
    && rm 0.4.0.tar.gz

##############################
# Eigen
##############################
RUN apt-get update -y -qq \
    && apt-get install -y -qq --no-install-recommends \
        libeigen3-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

##############################
# NL Optimization
##############################
RUN git clone https://github.com/stevengj/nlopt /tmp/nlopt \
    && cd /tmp/nlopt \
    && mkdir build \
    && cd build \
    && cmake \
        -D CMAKE_BUILD_TYPE=Release \
        -D NLOPT_PYTHON=OFF \
        -D NLOPT_OCTAVE=OFF \
        -D NLOPT_MATLAB=OFF \
        -D NLOPT_GUILE=OFF \
        -D NLOPT_SWIG=OFF \
        .. \
    && make -j$(($(nproc)-1)) \
    && make install \
    && rm -rf /tmp/*

##############################
# OSQP Solver
##############################
RUN git clone --recursive https://github.com/osqp/osqp /tmp/osqp \
    && cd /tmp/osqp \
    && mkdir build \
    && cd build \
    && cmake \ 
        -G "Unix Makefiles" \
        .. \
    && make -j$(($(nproc)-1)) \
    && make install \
    && rm -rf /tmp/*

##############################
# Catch2
##############################
RUN git clone https://github.com/catchorg/Catch2.git /tmp/Catch2 \
    && cd /tmp/Catch2 \
    && mkdir build \
    && cd build \
    && cmake \ 
        -D BUILD_TESTING=OFF \
        .. \
    && make -j$(($(nproc)-1)) \
    && make install \
    && rm -rf /tmp/*

# # (Optional) Set Clang as the default compiler
# ENV CC=/usr/bin/clang
# ENV CXX=/usr/bin/clang++
nicolapiccinelli commented 11 months ago

Hello @pwintz you probably reported the output from the terminal not properly because the command you wrote to compile and the command in the output do not match.

I'm having trouble getting a C++ file to compile when I include any libmpc headers. Here's a MWE:

// A file named "test_libmpc.cpp"
#include <mpc/IComponent.hpp>

To compile, I'm running

g++ -c test_libmpc.cpp -I ~/libmpc-0.4.0/include/ -I /usr/include/eigen3/ -std=c++20

where ~/libmpc-0.4.0 is the path to libmpc and /usr/include/eigen3 is the path to the Eigen installation.

The error I get is as follows:

root@pwintz-2-in-1:~# g++ -c test_libmpc.cpp -I ~/libmpc-0.4.0/include/ -I /usr/include/eigen3/
In file included from test_libmpc.cpp:1:
/root/libmpc-0.4.0/include/mpc/IComponent.hpp:25:23: error: non-type template parameters of class type only available with '-std=c++20' or '-std=gnu++20'
   25 |     template <MPCSize sizer>
      |                       ^~~~~
/root/libmpc-0.4.0/include/mpc/IComponent.hpp:26:45: error: expected template-name before '<' token
   26 |     class IComponent : public IDimensionable<sizer>
      |                                             ^
/root/libmpc-0.4.0/include/mpc/IComponent.hpp:26:45: error: expected '{' before '<' token

My setup is based on the Dockerfile included in the libmpc repository modified to also download libmpc to my user directory (/root/libmpc-0.4.0). Here's my version of the Dockerfile:

FROM ubuntu:latest

ENV DEBIAN_FRONTEND=noninteractive
WORKDIR /

##############################
# Core tools
##############################

RUN apt-get update -y -qq \
    && apt-get install -y -qq --no-install-recommends \
        apt-utils \
        lsb-release \
        build-essential \
        software-properties-common \
        ca-certificates \
        gpg-agent \
        wget \
        git \
        cmake \
        lcov \
        gcc \
        clang \
        clang-tidy \
        clang-format \
        libomp-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

##############################
# Non-root user Setup
##############################
ARG USERNAME=dev
RUN apt-get update -qq \
    && apt-get install -y --no-install-recommends \
        sudo \
        gosu \
    && rm -rf /var/lib/apt/lists/* \
    && useradd --create-home --home-dir /home/$USERNAME --shell /bin/bash --user-group --groups adm,sudo $USERNAME \
    && echo $USERNAME:$USERNAME | chpasswd \
    && echo $USERNAME ALL=\(ALL\) NOPASSWD:ALL >> /etc/sudoers \
    && touch home/$USERNAME/.sudo_as_admin_successful \
    && gosu $USERNAME mkdir -p /home/$USERNAME/.xdg_runtime_dir
ENV XDG_RUNTIME_DIR=/home/$USERNAME/.xdg_runtime_dir

##############################
# libMPC++
##############################
# Downloads and unzips lipmpc into the home directory.
RUN cd ~ && wget https://github.com/nicolapiccinelli/libmpc/archive/refs/tags/0.4.0.tar.gz \
    && tar -xzvf 0.4.0.tar.gz \
    && rm 0.4.0.tar.gz

##############################
# Eigen
##############################
RUN apt-get update -y -qq \
    && apt-get install -y -qq --no-install-recommends \
        libeigen3-dev \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

##############################
# NL Optimization
##############################
RUN git clone https://github.com/stevengj/nlopt /tmp/nlopt \
    && cd /tmp/nlopt \
    && mkdir build \
    && cd build \
    && cmake \
        -D CMAKE_BUILD_TYPE=Release \
        -D NLOPT_PYTHON=OFF \
        -D NLOPT_OCTAVE=OFF \
        -D NLOPT_MATLAB=OFF \
        -D NLOPT_GUILE=OFF \
        -D NLOPT_SWIG=OFF \
        .. \
    && make -j$(($(nproc)-1)) \
    && make install \
    && rm -rf /tmp/*

##############################
# OSQP Solver
##############################
RUN git clone --recursive https://github.com/osqp/osqp /tmp/osqp \
    && cd /tmp/osqp \
    && mkdir build \
    && cd build \
    && cmake \ 
        -G "Unix Makefiles" \
        .. \
    && make -j$(($(nproc)-1)) \
    && make install \
    && rm -rf /tmp/*

##############################
# Catch2
##############################
RUN git clone https://github.com/catchorg/Catch2.git /tmp/Catch2 \
    && cd /tmp/Catch2 \
    && mkdir build \
    && cd build \
    && cmake \ 
        -D BUILD_TESTING=OFF \
        .. \
    && make -j$(($(nproc)-1)) \
    && make install \
    && rm -rf /tmp/*

# # (Optional) Set Clang as the default compiler
# ENV CC=/usr/bin/clang
# ENV CXX=/usr/bin/clang++
pwintz commented 11 months ago

Ah, right, that was an old error message before I figured out that I needed -std=c++20. Here's an updated compile command and error message:

root@pwintz-2-in-1:~# g++ -c test_libmpc.cpp -I ~/libmpc-0.4.0/include/ -I /usr/include/eigen3/ -std=c++20
In file included from test_libmpc.cpp:2:
/root/libmpc-0.4.0/include/mpc/IComponent.hpp:27:45: error: expected template-name before '<' token
   27 |     class IComponent : public IDimensionable<sizer>
      |                                             ^
/root/libmpc-0.4.0/include/mpc/IComponent.hpp:27:45: error: expected '{' before '<' token
pwintz commented 11 months ago

I figured out that the compilation was failing because IDimensionable is not loaded. Adding the following line to IComponent.hpp fixes the problem:

#include <mpc/IDimensionable.hpp>
nicolapiccinelli commented 11 months ago

@pwintz good to know. The best way to include the library is to use the header for the linear LMPC.hpp or non-linear mpc NLMPC.hpp based on your specific application.