【问题标题】:Order of preference for SFINAE template?SFINAE 模板的优先顺序?
【发布时间】:2014-06-04 02:41:03
【问题描述】:

我正在尝试实现采用版本参数的模板化结构。

这是一个简化的例子:

template<int Version, class Enable = void>
struct Foo
{
};

template<int Version, class Enable = void>
struct Bar
{
};

/* Base Version of Foo */
template<int Version>
struct Foo<Version, typename enable_if<(Version > 0)>::type>
{
    int i;
};

/* Base Version of Bar */
template<int Version>
struct Bar<Version, typename enable_if<(Version > 0)>::type>
{
    Foo<Version> foo;
    float f;
};

/* Version 2 of Bar */
template<int Version>
struct Bar<Version, typename enable_if<(Version >= 2)>::type>
{
    Foo<Version> foo;
    float f;
    int extraParam;
};

使用这种方法,当我使用“Bar”时会产生歧义,因为 2 同时满足基本版本的条件(版本 > 0)和版本 2 的条件(版本 >= 2)。

我可以将基础更改为要求“版本 > 0 && 版本

【问题讨论】:

  • ...你可以使用重载解析:coliru.stacked-crooked.com/a/5a8f5315c7599361我尝试了类似的纯粹基于部分排序的东西,但不知何故 enable_if 干扰..
  • 递归方法很好,重载决议...嗯 :) 您忘记提及的关键是,对于每个新版本,您都必须向选择器添加一个额外的参数。跨度>
  • @DavidRodríguez-dribeas True.. 您也可以使用 42 个整数并希望获得最好的结果;)——或者您可以使用 Xeo's technique from here 来解决重载问题。
  • @dyp 还注意到 enable_if_t 在递归方法中是无用的

标签: c++ sfinae


【解决方案1】:

使用dyp提供的example link,我能够通过递归解决问题。

#include <iostream>
#include <type_traits>

using namespace std;

template<int Version>
struct Foo
{
    constexpr static bool is_valid = false;
};

template<int Version>
struct Bar
{
    constexpr static bool is_valid = false;
};

struct ValidVersion { constexpr static bool is_valid = true; };

/* Base Version of Foo */
template<>
struct Foo<0> : ValidVersion
{
    int i;
};

/* Base Version of Bar */
template<>
struct Bar<0> : ValidVersion
{
    Foo<0> foo;
    float f;
};

/* Version 2 of Bar */
template<>
struct Bar<2> : ValidVersion
{
    Foo<2> foo;
    float f;
    int extraParam;
    int extraParam2;
};

template<template<int V> class _Tp, int Version>
struct VersionSelectorImpl
{
    template<class T>
    struct wrap { using type = T; };
    using type = typename std::conditional<_Tp<Version>::is_valid, wrap<_Tp<Version>>, VersionSelectorImpl<_Tp, Version-1>>::type::type;
};

template<template<int V> class _Tp, int Version>
using VersionSelector = typename VersionSelectorImpl<_Tp, Version>::type;

int main() {
    cout << "sizeof(<Bar, 1>): " << sizeof(VersionSelector<Bar, 1>) << '\n';
    cout << "sizeof(<Bar, 2>): " << sizeof(VersionSelector<Bar, 2>) << '\n';
}

输出:

sizeof(): 12
sizeof(): 16

【讨论】:

    猜你喜欢
    • 2019-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-21
    • 1970-01-01
    • 2017-10-06
    相关资源
    最近更新 更多