określić typ ciągu swojej klasie Handle
, i odnoszą się do tego typu wewnątrz makeTypeErasedCallbackHandle()
:
#include <memory>
#include <string>
template <typename... FArgs>
struct Callback {
struct Handle {
using callback_type = Callback<FArgs...>;
};
};
struct BaseCallbackHandle {
};
using TypeErasedCallbackHandle = std::unique_ptr<BaseCallbackHandle>;
template <typename H>
TypeErasedCallbackHandle makeTypeErasedCallbackHandle(H handle) {
using callback_type = typename H::callback_type;
return {};
}
int main() {
Callback<int>::Handle h;
std::string s;
makeTypeErasedCallbackHandle(h); //should compile fine
makeTypeErasedCallbackHandle(s); //should raise a compile error
}
Live example
to zawiedzie podczas instancji dla każdego H
że nie określa typu zagnieżdżonego.
Z trochę więcej wysiłku, można static_assert
produkować znaczącą wiadomość do klienta, przy jednoczesnym zwiększeniu elastyczności poprzez rozwiązania typu cech. Ma to tę zaletę, że callback_impl::is_callback
mogą być specjalnie przystosowane do dowolnych typów uchwytu:
#include <memory>
#include <string>
namespace callback_impl {
struct callback_identification_type {};
template <typename T, typename = void>
struct is_callback : std::false_type {};
template <typename T>
struct is_callback<T,
std::enable_if_t<std::is_same<typename T::callback_id_type,
callback_identification_type>::value>>
: std::true_type {};
}
template <typename... FArgs>
struct Callback {
struct Handle {
using callback_id_type = callback_impl::callback_identification_type;
};
};
struct BaseCallbackHandle {
};
using TypeErasedCallbackHandle = std::unique_ptr<BaseCallbackHandle>;
template <typename H>
TypeErasedCallbackHandle makeTypeErasedCallbackHandle(H handle) {
static_assert(callback_impl::is_callback<H>::value,
"The handle type is not a member of a recognised Callback<T...>");
return {};
}
int main() {
Callback<int>::Handle h;
std::string s;
makeTypeErasedCallbackHandle(h); //should compile fine
makeTypeErasedCallbackHandle(s); //should raise a compile error
return 0;
}
Live example
wyjściowy:
g++ -std=c++14 -O2 -Wall -Wno-unused-local-typedefs -pedantic -pthread main.cpp && ./a.out
main.cpp: In instantiation of 'TypeErasedCallbackHandle makeTypeErasedCallbackHandle(H) [with H = std::__cxx11::basic_string<char>; TypeErasedCallbackHandle = std::unique_ptr<BaseCallbackHandle>]':
main.cpp:41:35: required from here
main.cpp:32:5: error: static assertion failed: The handle type is not a member of a recognised Callback<T...>
static_assert(callback_impl::is_callback<H>::value,
^~~~~~~~~~~~~
Możliwe duplikat [Doing static \ _assert, że typ szablonu jest innym szablonem] (http: // stackoverflow.com/questions/17390605/doing-a-static-assert-that-a-template-type-is-another-template) –