c++winapic++14winlamb

WinLamb error: illegal member initialization


I'm trying to learn how to use WinLamb, a lightweight modern C++ library for Win32 API, headers only, using C++11 lambdas to handle Windows messages.
I've created an empty Win32 project in Visual Studio 2017 and added the two files as in the example at the top of Codeproject article (the same of Github WinLamb page). The only file included is <winlamb/window_main.h>.
Trying to compile, I get the following errors (both on line 45 of <winlamb/internals/window.h>):

C2614 wl::wli::window <wl::wli::w_thread_capable<LRESULT,0>>::_styler' illegal member initialization: 'styler' is not a base or member
and
C2512 'wl::wli::styler<wl::wli::window<wl::wli::w_thread_capable<LRESULT,0>>>': no appropriate default constructor available

The whole code for this minimal sample application consists of two files:
My_Window.h

#pragma once
#include <winlamb/window_main.h>

class My_Window : public wl::window_main {
public:
    My_Window();
};

and My_Window.cpp

#include "My_Window.h"

RUN(My_Window) // optional, generate WinMain call and instantiate My_Window

My_Window::My_Window()
{
    setup.wndClassEx.lpszClassName = L"SOME_CLASS_NAME"; // class name to be registered
    setup.title = L"This is my window";
    setup.style |= WS_MINIMIZEBOX;

    on_message(WM_CREATE, [this](wl::wm::create p)->LRESULT
    {
        set_text(L"A new title for the window");
        return 0;
    });

    on_message(WM_LBUTTONDOWN, [](wl::wm::lbuttondown p)->LRESULT
    {
        bool isCtrlDown = p.has_ctrl();
        long xPos = p.pos().x;
        return 0;
    });
}

Looking at file <winlamb/internals/window.h> we note that it includes the following headers:

#include "w_thread_capable.h"
#include "w_user_control.h"
#include "styler.h"

The errors seem to have to do with the w_thread_capable class. The template class w_thread_capable has only a single (protected) constructor. I tried to change it to public, but I got the same errors. Here a portion of file <winlamb/internals/window.h> where I get the error:

template<typename baseT>
class window : public baseT {
// ...
private:

    class _styler final : public wli::styler<window> {
    public:
    // error here:
        explicit _styler(window* pWindow) noexcept : styler(pWindow) { }
    };
// ...  
};

Here is the code of styler class (file: <winlamb/internals/styler.h>):

/**
 * Part of WinLamb - Win32 API Lambda Library
 * https://github.com/rodrigocfd/winlamb
 * Copyright 2017-present Rodrigo Cesar de Freitas Dias
 * This library is released under the MIT License
 */

#pragma once
#include <Windows.h>

namespace wl {
namespace wli {

// Wraps window style changes with Get/SetWindowLongPtr, and allows custom methods.
template<typename wndT>
class styler {
private:
    wndT& _wnd;

protected:
    explicit styler(wndT* target) noexcept : _wnd(*target) { }

public:
    styler(const styler&) = delete;
    styler& operator=(const styler&) = delete; // non-copyable, non-movable

protected:
    HWND  hwnd() const noexcept   { return this->_wnd.hwnd(); }
    wndT& target() const noexcept { return this->_wnd; }

public:
    wndT& set_style(bool addStyle, DWORD styleFlags) noexcept {
        return this->_change_style_flags(false, addStyle, styleFlags);
    }

    wndT& set_style_ex(bool addStyle, DWORD styleFlags) noexcept {
        return this->_change_style_flags(true, addStyle, styleFlags);
    }

    bool has_style(DWORD styleFlags) const noexcept {
        return (GetWindowLongPtrW(this->_wnd.hwnd(), GWL_STYLE) & styleFlags) != 0;
    }

    bool has_style_ex(DWORD styleFlags) const noexcept {
        return (GetWindowLongPtrW(this->_wnd.hwnd(), GWL_EXSTYLE) & styleFlags) != 0;
    }

private:
    wndT& _change_style_flags(bool isEx, bool addStyle, DWORD styleFlags) noexcept {
        LONG_PTR curFlags = GetWindowLongPtrW(this->_wnd.hwnd(), isEx ? GWL_EXSTYLE : GWL_STYLE);
        if (addStyle) {
            curFlags |= static_cast<LONG_PTR>(styleFlags);
        } else {
            curFlags &= ~static_cast<LONG_PTR>(styleFlags);
        }
        SetWindowLongPtrW(this->_wnd.hwnd(), isEx ? GWL_EXSTYLE : GWL_STYLE, curFlags);
        return this->_wnd;
    }
};

}//namespace wli
}//namespace wl

I honestly can not understand this code.
Every suggestion is appreciated.


Solution

  • Modify definition of class _styler in winlamb/internals/window.h to explicitly specify full class template in base initializer.

    class _styler final : public wli::styler<window> {
    public:
        // Error in VC 2017
        //explicit _styler(window* pWindow) noexcept : styler(pWindow) { }
        // No errors
        explicit _styler(window* pWindow) noexcept : wli::styler<window>(pWindow) { }
    };
    

    or

    class _styler final : public styler<window> {
    public:
        explicit _styler(window* pWindow) noexcept : styler<window>(pWindow) { }
    };