mardi 20 juillet 2021

c++11 compile time error in template member initialization list with lambda

First of all, I don't know English well, but I'll try to eplain my problem. So, I'm writing heap allocated Any class (the analogue of c++17 std::any) using c++11 for educational purposes. I'm writing it in VisualStudio 2015.

The error appears here:

template<typename T>
Any::AnyHandler::AnyHandler(AnyType<T>&&) :
   type{ []() -> std::type_info const& { return typeid(AnyType_t<T>); } },
   clone{ [](void* data) -> void* { return new AnyType_t<T>(*static_cast<AnyType_t<T>*>(data)); } },
   move{ [](void*& data) -> void* { return std::exchange(data, nullptr); } },
   destroy{ [](void*& data) -> void { delete static_cast<AnyType_t<T>*>(std::exchange(data, nullptr)); } },
   empty{ [](void* data) -> bool { return data == nullptr; } }
{}

Where AnyType_t is

template <typename T>
struct AnyType
{
   using type = std::remove_reference_t<T>;
};

template<typename T>
using AnyType_t = typename AnyType<T>::type;

I uses AnyType instance to just pass T type as parameter in AnyHandler constructor.

The description of the error is next

1>E:\Downloads\Any-main\any\Any-main\src/Any.h(68): error C2065: 'T': undeclared identifier
1>E:\Downloads\Any-main\any\src\main.cpp(25): note: see reference to function template instantiation 'Any::AnyHandler::AnyHandler<double>(Any::AnyType<double> &&)' being compiled
1>E:\Downloads\Any-main\any\Any-main\src/Any.h(68): error C2923: 'Any::AnyType_t': 'T' is not a valid template type argument for parameter 'T'
1>E:\Downloads\Any-main\any\Any-main\src/Any.h(69): error C2065: 'T': undeclared identifier
1>E:\Downloads\Any-main\any\Any-main\src/Any.h(69): error C2923: 'Any::AnyType_t': 'T' is not a valid template type argument for parameter 'T'
1>E:\Downloads\Any-main\any\Any-main\src/Any.h(71): error C2065: 'T': undeclared identifier
1>E:\Downloads\Any-main\any\Any-main\src/Any.h(71): error C2923: 'Any::AnyType_t': 'T' is not a valid template type argument for parameter 'T'

The place where the constructor of AnyHandler is called from is next

template<typename T>
Any::Any(T&& value) :
   _handler{ AnyType<T>{} },
   _data{ new AnyType_t<T>{std::forward<T>(value)} }
{}

And it's weird, becaus if I change AnyHandler's constructor with the following code

template<typename T>
Any::AnyHandler::AnyHandler(AnyType<T>&&)
{
    type = []() -> std::type_info const& { return typeid(AnyType_t<T>); };
    clone = [](void* data) -> void* { return new AnyType_t<T>(*static_cast<AnyType_t<T>*>(data)); };
    move = [](void*& data) -> void* { return std::exchange(data, nullptr); };
    destroy = [](void*& data) -> void { delete static_cast<AnyType_t<T>*>(std::exchange(data, nullptr)); };
    empty = [](void* data) -> bool { return data == nullptr; };
}

It compiles just fine. Btw, all handler members (type, clone, move and so on) are just function pointers not std::function.

So, I wonder why it's happen.

Aucun commentaire:

Enregistrer un commentaire