vendredi 22 septembre 2017

Why am I getting no known convertion error?

I have such a code:

struct AnyResolver {
    template<typename T> operator T() {
        return Resolve<typename std::remove_pointer<T>::type>();
    }
};

template<typename, typename T, typename ...Ts> struct IsConstructable_ : std::false_type {};
template<typename T, typename... Ts> struct IsConstructable_<void_t<decltype(T(std::declval<Ts>()...))>, T, Ts...> : std::true_type {};

template<typename T, typename... Ts> using IsConstructable = IsConstructable_<void_t<>, T, Ts...>;

template<bool E, typename T, typename... Args> struct DiConstructor {
    static T* construct(Args... args) {
        return reinterpret_cast<T*>(0);
    }
};

template<typename T, typename... Args> struct DiConstructor<true, T, Args...> {
    static T* construct(Args... args) {
        return new T(args...);
    }
};

template<typename T> T* ConstructIfPossible() {
    if (IsConstructable<T, DiMark&&, decltype(AnyResolver())>{}) {
        return DiConstructor<IsConstructable<T, DiMark&&, decltype(AnyResolver())>{},
                             T,
                             DiMark&&,
                             decltype(AnyResolver())>::construct(std::move(DiMark{}), AnyResolver{});
    } else {
        return new T(std::move(DiMark{}), AnyResolver());
    }
}

}

When I try to compile it I'm getting this:

./type_holder.h:45:14: error: no matching constructor for initialization of 'test_class'
                return new T(args...);
                           ^ ~~~~
./type_holder.h:54:35: note: in instantiation of member function 'di::DiConstructor<true, test_class, di::DiMark &&, di::AnyResolver>::construct' requested
      here
                                                         decltype(AnyResolver())>::construct(std::move(DiMark{}), AnyResolver{});
                                                                                   ^
test.cc:26:19: note: in instantiation of function template specialization 'di::ConstructIfPossible<test_class>' requested here
        std::cout << di::ConstructIfPossible<test_class>() << std::endl;
                         ^
test.cc:14:9: note: candidate constructor not viable: no known conversion from 'di::DiMark' to 'di::DiMark &&' for 1st argument
        INJECT(test_class, int* a) {}
               ^
./inject_markers.h:6:36: note: expanded from macro 'INJECT'
#define INJECT(name, ...) explicit name(di::DiMark&& m, __VA_ARGS__)
                                   ^
test.cc:12:7: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
class test_class {
      ^
test.cc:12:7: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
1 error generated.

The question is what amI doing wrong? Why does compiler tells me that I'm trying to convert DiMark to DiMark&&? Should it not be DiMark&& already since I did std::move(DiMark) {} explicitly converting lvalue to rvalue?

Aucun commentaire:

Enregistrer un commentaire