Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 扩展两个类的参数的语法_C++_Inheritance - Fatal编程技术网

C++ 扩展两个类的参数的语法

C++ 扩展两个类的参数的语法,c++,inheritance,C++,Inheritance,在Java中,一个参数可以实现多个接口。您必须使用泛型语法,但您可以: public <T extends Appendable & Closeable> void spew(T t) { t.append("Bleah!\n"); if (timeToClose()) t.close(); } 编写一个函数来获取一个ICloseable(这只是多态性): 但是一个函数的签名是什么,它采用了一个参数,如Java示例中所示,该参数继承自IClo

在Java中,一个参数可以实现多个接口。您必须使用泛型语法,但您可以:

public <T extends Appendable & Closeable> void spew(T t) {
    t.append("Bleah!\n");
    if (timeToClose())
        t.close();
}
编写一个函数来获取一个
ICloseable
(这只是多态性):


但是一个函数的签名是什么,它采用了一个参数,如Java示例中所示,该参数继承自
ICloseable
IAppendable

以下是仅使用标准工具编写它的方法:

template <class T>
std::enable_if_t<
    std::is_base_of<IAppendable, T>{} && std::is_base_of<ICloseable, T>{},
    void
> closeThis(T &t) {
    t.append("end");
    t.close();
}

@昆汀出色的回答促使我编写了一个广义的、可变的
inherits
模板。它允许您轻松地指定任意数量的基类

#include <type_traits>

template<class... T> struct inherits :
    std::true_type
{};

template<class T, class Base1, class... Bases>
struct inherits<T, Base1, Bases...> :
    std::conditional_t< std::is_base_of<Base1, T>{},
        inherits<T, Bases...>,
        std::false_type
    >
{};
#包括
模板结构继承:
std::真_类型
{};
模板
结构继承:
std::conditional_t
{};
第一个模板参数是要检查的类型,其余参数是第一个类型必须从中继承的类型

比如说,

class A {};
class B {};
class C {};

template<class T>
std::enable_if_t<
    inherits<T, A, B, C>{},
    void
> foo(const T& t)
{
    // ...
}
A类{};
B类{};
C类{};
模板
std::如果启用,则启用<
继承{},
无效的
>foo(施工及测试)
{
// ...
}
在这里,作为参数传递给
foo
的任何类型
T
都必须继承自
A
B
C


问题是:如何实现一个既源于
IAppendable
又源于
ICloseable
的类?或者:如何创建模板化类/函数/etc。其
typename T
参数必须同时包含
IAppendable
ICloseable
?后者(为了清晰起见,我进行了编辑)。实现一个同时实现两者的类很简单:
class a:public-IAppendable,public-ICloseable{}很有趣,谢谢!在返回类型上使用SFINAE是唯一的方法吗?(我感觉错误消息与实际的程序员错误并不相关。)@Thirty340我认为,当概念最终进入语言时,将有助于为这些需求定义更清晰的语法。现在,这是惯用的方式,非常友好。取消对
One
行的注释将触发一条错误消息,其中包含
candidate:template std::enable\u if\u t closeThis(t&)
。不太理想,但对于模板错误来说也不是那么糟糕;)我不确定
is_base\u of
是正确的检查,因为它还检测不明确和不可访问的基。(当然,如果我们使用的是模板,我根本不明白为什么我们需要这些基类。)@t.C.我认为
是可转换的,但这涵盖了不太有用的情况(赋值的左侧)和更模糊的情况(私下从接口继承??)。将函数限制为一组接口基本上会禁用duck类型,根据具体情况,duck类型可能过于自由。我为您的
所有基础编写了一个可变实现,请参见我的答案。让我知道它是否可以改进。很好的实现:)另外,我是个傻瓜,错过了
allTrue
函数的复制粘贴…谢谢!我以为你故意把它作为练习留给读者:D
constexpr bool allTrue() {
    return true;
}

template <class... Bools>
constexpr bool allTrue(bool b1, Bools... bools) {
    return b1 && allTrue(bools...);
}

template <class T, class... Bases>
struct all_bases {
    static constexpr bool value = allTrue(std::is_base_of<Bases, T>{}...);

    constexpr operator bool () const {
        return value;
    }
};

template <class T>
std::enable_if_t<
    all_bases<T, IAppendable, ICloseable>{},
    void
> closeThis(T &t) {
    t.append("end");
    t.close();
}
#include <type_traits>

template<class... T> struct inherits :
    std::true_type
{};

template<class T, class Base1, class... Bases>
struct inherits<T, Base1, Bases...> :
    std::conditional_t< std::is_base_of<Base1, T>{},
        inherits<T, Bases...>,
        std::false_type
    >
{};
class A {};
class B {};
class C {};

template<class T>
std::enable_if_t<
    inherits<T, A, B, C>{},
    void
> foo(const T& t)
{
    // ...
}