如何确保一个类在C++中扩展了一个实现?

huangapple go评论65阅读模式
英文:

How do I guarantee that a class extends an implementation in c++?

问题

在C++中,你可以使用模板特化和类型限定来实现与Java中的类似功能。你可以使用以下方式来要求类型T实现IFoo接口:

template <typename T>
class container {
public:
    // ... implementation

    void addElement(T element) {
        // 使用std::tuple的方式来获取position
        auto pos = element.position();
        if (std::get<0>(pos) > 10) {
            // ... 做一些操作
        }
    }
};

在这个示例中,我们没有使用类似Java中的继承方式来限定类型T,而是直接要求类型T拥有position()和dimension()成员函数。如果类型T不符合这些要求,编译时将会出现错误。这种方式称为"模板要求",它依赖于类型T的实际属性而不是继承关系。

所以,你可以通过这种方式在C++中达到类似Java中的要求效果,而不需要显式地指定继承关系。

英文:

So say I have an interface that I want to use to specify specific properties a class should have in a container

class IFoo {
     virtual std::tuple&lt;int, int&gt; position()= 0;
     virtual std::tuple&lt;int, int&gt; dimension()= 0;
}

and I have a class that uses this interface

class Foo: public IFoo {
     ... implementation
}

and I have a container that I am creating

template &lt;typename T&gt;
class container {
      ... implementation
}

I want to demand that T uses the interface IFoo so that I can access the functions position and dimension of any generic object of type T. For example:

void container::addElement(T element){
     if(std::get&lt;0&gt;(element.position()) &gt; 10){
            ... do stuff
     }
}

In java, it would be:

class container&lt;T extends IFoo&gt;

How do I do the equivalent in C++?

答案1

得分: 3

由于您正在使用C++17,最简单的解决方案是使用类型特征和std::enable_if_t

#include <tuple>
#include <type_traits>

class IFoo {
     virtual std::tuple<int, int> position() = 0;
     virtual std::tuple<int, int> dimension() = 0;
};

template<typename T,
    typename = std::enable_if_t<std::is_base_of_v<IFoo, T>>>
class Container {

};


class Foo : public IFoo {
};

class Bar {};

Container<Foo> foo; // OK

Container<Bar> bar; // ERROR

一旦您升级到C++20,您可以使用概念:

#include <tuple>
#include <type_traits>

class IFoo {
     virtual std::tuple<int, int> position() = 0;
     virtual std::tuple<int, int> dimension() = 0;
};

template<typename T>
concept implementsIfoo = std::is_base_of<IFoo, T>::value;

template<implementsIfoo T>
class Container {

};


class Foo : public IFoo {
};

class Bar {};

Container<Foo> foo; // OK

Container<Bar> bar; // ERROR
英文:

Since you're using C++17, the simplest solution is to use type traits and std::enable_if_t:

#include &lt;tuple&gt;
#include &lt;type_traits&gt;

class IFoo {
     virtual std::tuple&lt;int, int&gt; position()= 0;
     virtual std::tuple&lt;int, int&gt; dimension()= 0;
};

template&lt;typename T,
	typename=std::enable_if_t&lt;std::is_base_of_v&lt;IFoo, T&gt;&gt;&gt;
class Container {

};


class Foo: public IFoo {
};

class Bar {};

Container&lt;Foo&gt; foo; // OK

Container&lt;Bar&gt; bar; // ERROR

And once you've updated to C++20 you can use concepts:

#include &lt;tuple&gt;
#include &lt;type_traits&gt;

class IFoo {
     virtual std::tuple&lt;int, int&gt; position()= 0;
     virtual std::tuple&lt;int, int&gt; dimension()= 0;
};

template&lt;typename T&gt;
concept implementsIfoo = std::is_base_of&lt;IFoo, T&gt;::value;

template&lt;implementsIfoo T&gt;
class Container {

};


class Foo: public IFoo {
};

class Bar {};

Container&lt;Foo&gt; foo; // OK

Container&lt;Bar&gt; bar; // ERROR

huangapple
  • 本文由 发表于 2023年7月10日 10:40:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76650375.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定