仅为特定模板类启用模板 [英] Enable template only for specific templated class

查看:157
本文介绍了仅为特定模板类启用模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

此问题的灵感来自我之前的问题没有模板参数推导参数包

This question is inspired from my previous question 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 )允许为 H Callback< int> :: Handle 的示例必须编译,而 std :: string >

The function template makeTypeErasedCallbackHandle now takes any class as input parameter. Is there any way to ensure (e.g. with static-assert or enable_if), that only Callback<FArgs...>::Handle (with any FArgs) is allowed as H? The example with Callback<int>::Handle shall compile, while std::string shall fail.

推荐答案

Handle 类中定义一个类型, code> makeTypeErasedCallbackHandle()

Define a type within your Handle class, and refer to that type inside 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
}

实例

这将在任何<$ c $的实例化期间失败c> H 不定义嵌套类型。

This will fail during instantiation for any H that doesn't define the nested type.

,您可以 static_assert 向客户端生成有意义的消息,同时通过类型traits增加解决方案的灵活性。这有一个优点, callback_impl :: is_callback 可以专门用于任意句柄类型:

With a little more effort, you can static_assert to produce a meaningful message to the client, while at the same time increasing the flexibility of the solution via type traits. This has the advantage that callback_impl::is_callback can be specialised for arbitrary handle types:

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

这篇关于仅为特定模板类启用模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆