gpt4 book ai didi

c++ - 使用 SFINAE 检查类型是否可以绑定(bind)到模板模板参数

转载 作者:搜寻专家 更新时间:2023-10-31 01:35:59 27 4
gpt4 key购买 nike

是否可以测试某些类型是否可以通过 SFINAE 绑定(bind)到模板模板参数?

我认为我尝试做的最好用下面的示例代码来解释:

#include <iostream>

template<typename... T> using void_t = void;

template<typename T> struct TemporaryBindObject
{
using type = TemporaryBindObject<T>;
};

template<template<typename...> class Dest> struct TestValidBind
{
template<typename... Ts> struct toTypesOf
{
using type = std::false_type;
};
template<template<typename...> class Src, typename... Ts> struct toTypesOf<Src<Ts...>, void_t<Dest<Ts...,float>>>
{
using type = std::true_type;
};
};

template<typename T> struct OneParamStruct{};
template<typename T1, typename T2> struct TwoParamStruct{};

int main()
{
using tmp = TemporaryBindObject<int>;

std::cout << "Can bind to TwoParamStruct: " << TestValidBind<TwoParamStruct>::toTypesOf<tmp>::type::value << std::endl;
std::cout << "Can bind to OneParamStruct: " << TestValidBind<OneParamStruct>::toTypesOf<tmp>::type::value << std::endl;
}

首先我创建了一个临时类型 tmp我想从中获取模板参数 int将其绑定(bind)到另一个类模板。随着TestValidBind<template template type>::toTypesOf<typename>我想测试是否可以将给定类型的参数绑定(bind)到 template template parameter and 并附加一个附加类型(示例中为 float)。

我想要的是TestValidBind<TwoParamStruct>::toTypesOf<tmp>::typetrue_type同时 TestValidBind<OneParamStruct>::toTypesOf<tmp>::typefalse_type .


代码示例不使用 g++ -std=c++11 编译(5.3.1) 出现以下错误:

../test_SFINAE_with_template_binding.cc: In function ‘int main()’: ../test_SFINAE_with_template_binding.cc:34:96: error: ‘TestValidBind<OneParamStruct>::toTypesOf<TemporaryBindObject<int> >::type’ has not been declared

和报告 false_type (这是错误的)如果 OneParamStruct行已删除。

clang++ -std=c++11 (3.8.0) 代码编译但报告 false_type在这两种情况下。

这样的事情有可能吗?


编辑:void 更改附加类型至 float突出显示我想检查附加类型是否可行。

最佳答案

void_t技巧要求我们为主模板的参数之一提供默认类型 void .您不需要主模板 ( toTypesOf) 是可变的。

bool 更符合惯用语从 false_type 继承的类型特征或 true_type而不是嵌套 type .不需要 TemporaryBindObject有一个嵌套的 type .

TestValidBind应该看起来像这样:

template<template<typename...> class Dest> struct TestValidBind
{
template<template<typename...> class Dest, typename T, typename = void_t<>> struct toTypesOf
: std::false_type
{};
template<template<typename...> class Dest, template<typename...> class Src, typename... Ts> struct toTypesOf<Dest, Src<Ts...>, void_t<Dest<Ts..., float>>>
: std::true_type
{};
};

编辑: 正如您所说,这不适用于 g++,我不知道为什么会这样。但我们可以简化它,看看是否有帮助。我们实际上并不需要封闭结构 TestValidBind . toTypesOf如果我们移植 Dest,模板可以在命名空间范围内参数:

template<template<typename...> class Dest, typename T, typename = void_t<>> struct toTypesOf
: std::false_type
{};
template<template<typename...> class Dest, template<typename...> class Src, typename... Ts> struct toTypesOf<Dest, Src<Ts...>, void_t<Dest<Ts..., float>>>
: std::true_type
{};

这适用于 g++。

DEMO

如果您愿意,我们可以更进一步,将所有内容放在 detail 中,使其更易于使用。命名空间并将其包装在别名模板中:

namespace detail
{
template<typename... T> using void_t = void;

template<typename... T> struct TemporaryBindObject {};

template<template<typename...> class Dest, typename T, typename = void_t<>> struct toTypesOf
: std::false_type {};
template<template<typename...> class Dest, template<typename...> class Src, typename... Ts> struct toTypesOf<Dest, Src<Ts...>, void_t<Dest<Ts...>>>
: std::true_type {};
}

template<template<typename...> class Dest, typename... Ts>
using IsValidBind = typename detail::toTypesOf<Dest, detail::TemporaryBindObject<Ts...>>;

template<template<typename...> class Dest, typename... Ts>
using IsValidBindWithFloat = IsValidBind<Dest, Ts..., float>;

template<template<typename...> class Dest, typename... Ts>
using IsValidBindWithVoid = IsValidBind<Dest, Ts..., void>;

std::cout << "Can bind to TwoParamStruct: " << IsValidBindWithFloat<TwoParamStruct, int>::value << std::endl;
std::cout << "Can bind to OneParamStruct: " << IsValidBindWithFloat<OneParamStruct, int>::value << std::endl;

现在我们不需要 using tmp ,我们有一个更通用的解决方案,您可以在其中轻松更改要用作附加类型的类型。

DEMO

关于c++ - 使用 SFINAE 检查类型是否可以绑定(bind)到模板模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36411565/

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