gpt4 book ai didi

c++ - 仅为特定模板类启用模板

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:42:57 26 4
gpt4 key购买 nike

这个问题的灵感来自于我之前的问题No template parameter deduction of parameter pack .

考虑以下代码示例:

#include <memory>
#include <string>

template<typename... FArgs>
class Callback
{
public:
class Handle{};
};

class BaseCallbackHandle
{
};

using TypeErasedCallbackHandle = std::unique_ptr<BaseCallbackHandle>;

template<typename H>
TypeErasedCallbackHandle makeTypeErasedCallbackHandle( H handle)
{
return {};
}

int main()
{
Callback<int>::Handle h;
std::string s;
makeTypeErasedCallbackHandle(h); //should compile fine
makeTypeErasedCallbackHandle(s); //should raise a compile error
}

另见 http://coliru.stacked-crooked.com/a/5f2a2e816eef6afd

函数模板makeTypeErasedCallbackHandle现在将任何类作为输入参数。有什么方法可以确保(例如使用 static-assert 或 enable_if),只有 Callback<FArgs...>::Handle (与任何 FArgs )被允许作为 HCallback<int>::Handle 的示例应编译,同时 std::string将失败。

最佳答案

Handle 类中定义一个类型,并在 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

对于任何未定义嵌套类型的 H,这将在实例化期间失败。


稍加努力,您就可以static_assert 向客户端生成有意义的消息,同时通过类型特征增加解决方案的灵 active 。这样做的好处是 callback_impl::is_callback 可以专用于任意句柄类型:

#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

输出:

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,
^~~~~~~~~~~~~

关于c++ - 仅为特定模板类启用模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37874287/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com