【问题标题】:How to select a specialization by non-type parameter如何通过非类型参数选择专业化
【发布时间】:2017-10-03 21:18:59
【问题描述】:

我想定义一个带有非类型参数的可变参数模板类,并使用一个嵌套模板类,我可以通过可变参数模板参数之一对其进行专门化。

我的问题类似于C++ variadic template with non-type parameters of different types。但我想对嵌套类进行专门化,作为所有者类的参数之一

struct Data
{
    std::string field1;
    std::string field2;
    bool field3 = false;
    int field4 = 0;
};

template <typename ... Types>
struct Wrapper
{
    template <Types ... Args>
    struct Holder
    {
    };
};

有效:

using W = Wrapper<decltype(&Data::field1), decltype(&Data::field2), decltype(&Data::field3), decltype(&Data::field4)>;
    using H = W::Holder<&Data::field1, nullptr, nullptr, nullptr>;

但我需要将其用作

using H = W::Holder<&Data::field3>;

我该如何实现?

类似的代码

#include <iostream>
#include <string>
#include <type_traits>

struct Data
{
    std::string field1;
    std::string field2;
    bool field3 = false;
    int field4 = 0;
};

struct Null;

template <typename T, T>
struct Holder
{
};

template <typename H, typename ... T>
struct Select
    : Select <T ... >
{
    using Base = Select <T ... >;
    using Base::Get;

    template <H F>
    static Holder<H, F> Get();
};

template <>
struct Select<Null>
{
    static void Get();
};

int main()
{
    using S = Select<std::string Data::*, bool Data::*, int Data::*, Null>;
    using H = decltype(S::Get<&Data::field3>());
    static_assert(std::is_same<H, Holder<decltype(&Data::field3), &Data::field3>>::value, "Problem ...");
    return 0;
};

但我需要在没有 decltype 和函数的情况下执行此操作

正确的解决方案是

using H = W::Holder<&Data::field3>;

【问题讨论】:

  • 对于初学者来说这是模棱两可的,&amp;Data::field1&amp;Data::field2 具有相同的类型,所以没有办法完成你想要的。此外,实际描述您想要解决的问题可能是有益的,可能是比您在此处走的路径更好的方式。
  • 是的,我有点误会了。所有类型都是唯一的。使用 W = Wrapper<:string data:: bool int>;问题是通过参数类型之一的值来选择实体专业化
  • @NirFriedman 你在说什么?发布的代码按原样编译。
  • @n.m.我的错,你是对的。不过,我认为“描述实际问题”的观察是成立的。
  • @Dmitry 请修正你的问题,而不是在这里说你犯了错误。

标签: c++ c++11


【解决方案1】:

由于您没有指定标准版本,我假设您没有偏好。好吧,在 C++17 中你可以这样做:

template<typename Type>
struct Base {
    template <Type>
    struct Holder {};
};

template <typename ... Types>
struct Wrapper: Base<Types>... {
    template<auto Arg>
    using Holder = typename Base<decltype(Arg)>::template Holder<Arg>;
};

至少只要它符合您的评论:

所有类型都是唯一的:using W = Wrapper&lt;std::string Data::*, bool Data::*, int Data::*&gt;;

以下只是按预期工作:

using W = Wrapper<decltype(&Data::field1), decltype(&Data::field3), decltype(&Data::field4)>;
using H = W::Holder<&Data::field3>;

wandbox 上查看。

【讨论】:

  • gcc 6.2.0 with -std=c++17 'error: 'auto' parameter not allowed in this context'。我想要 C++11
  • @Dmitry 它是带有 gcc 6 的 c++1z,不是吗?
【解决方案2】:

中,传递给模板的非类型值必须具有固定类型。这种类型可以依赖于以前的类型参数,但必须由它们固定。

您想将非类型参数作为第一个参数传递并给它一个可变类型。

没有可用的“模板重载解决方案”选项。

还有其他技巧,例如将标签分派到宏或其他任何东西,也可以解决您的问题。但是你已经指定了你想要的正是那个语法。

您的问题受到过度约束,无法按说明解决。

所以你运气不好。升级您的编译器版本并稍后再试,或者在您的下一个问题中删除不必要的限制。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-18
    • 2012-07-14
    • 1970-01-01
    • 1970-01-01
    • 2021-09-04
    • 1970-01-01
    相关资源
    最近更新 更多