【问题标题】:SFINAE and inheritanceSFINAE 和继承
【发布时间】:2020-06-19 08:39:10
【问题描述】:

我正在寻找以下问题的解决方案:

#include <string>

class A
{
public:
    template <typename T>
    static typename std::enable_if<std::is_same<T, std::string>::value, void>::type foo(T val)
    {
        printf("std::string\n");
    }

    template<typename T, typename... Arg>
    static void multiple(Arg&&... arg)
    {
        T::foo(arg...);
    }
};

class B : public A
{
public:
    template <typename T>
    static typename std::enable_if<std::is_same<T, int>::value, void>::type foo(T val)
    {
        printf("int\n");
    }
};

int main()
{
    std::string a;
    int b = 0;
    A::multiple<B>(a, b);
}

如果两个foo 方法都在同一个类中,或者我从适当的类中强制fooA::foo 用于std::stringB::foo 用于int),所有工作正常,但是我需要多个类,因为基类必须是可扩展的。我不能使用简单的专业化,因为我需要更多 SFINAE 功能,例如检测 std::pairstd::tuple 等。我也不想将 foo 方法从类移动到命名空间。你有什么想法我该如何解决这个问题?

【问题讨论】:

  • 为什么你首先需要所有这些 SFINAE'ing?另外,当您只专注于单参数 foo 时,“multiple”方法有什么用?
  • 这只是一个用于更高级目的的简单示例,我正在研究数据类型转换器,并且需要“多个”,因为我想在一次调用中转换所有类型。

标签: c++ templates inheritance sfinae


【解决方案1】:

这里B::foo隐藏A::foo,你需要一个using

class B : public A
{
public:
    using A::foo;

    template <typename T>
    static typename std::enable_if<std::is_same<T, int>::value, void>::type foo(T val)
    {
        printf("int\n");
    }
};

但是

来自namespace.udecl#15.sentence-1

当 using-declarator 将基类中的声明带入派生类时,派生类中的成员函数和成员函数模板会覆盖和/或隐藏同名的成员函数和成员函数模板,parameter-type-list , cv-qualification 和 ref-qualifier(如果有)在基类中(而不是冲突)

返回类型不算,所以你必须在参数中使用std::enable_if

class A
{
public:
    template <typename T>
    static void foo(T val, std::enable_if_t<std::is_same<T, std::string>::value, int> = 0)
    {
        printf("std::string\n");
    }

};

class B : public A
{
public:
    using A::foo;

    template <typename T>
    static void foo(T val, std::enable_if_t<std::is_same<T, int>::value, int> = 0)
    {
        printf("int\n");
    }
};

Demo

注意:你也有错别字

template<typename T, typename... Arg>
static void multiple(Arg&&... arg)
{
    T::foo(arg...); // B::foo(string, int)
}

应该是

template<typename T, typename... Arg>
static void multiple(Arg&&... arg)
{
    (T::foo(arg), ...); // B::foo(string), B::foo(int)
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2017-12-16
  • 2018-03-03
相关资源
最近更新 更多