c++ - 使用=delete 进行接口(interface)描述

标签 c++ c++11 sfinae

我正在尝试为一个自由函数 listenTo(SomeAnimal) 提供一个接口(interface)描述,该函数应该对满足特定类型要求的类型进行操作(它应该是一种动物)。函数参数不应使用纯虚方法的接口(interface)继承机制。

我破解了一个解决方案,其中自由函数通过基类的 sfinae 语句检查参数类型。为了保证参数实现基类的接口(interface),我使用 = delete 删除了基类方法。我没有在互联网上找到任何类似的解决方案,因此,我不确定它是否有意义,但它确实有效。

到这里,有什么意见吗?

#include <iostream>
#include <type_traits>

class IAnimal {
public:
    // Interface that needs to be implemented
    std::string sound() const = delete;
protected:
    IAnimal(){}
};


class Cat : public IAnimal {
public:
    // Implements deleted method
    std::string sound() const {
        return std::string("Meow");
    }

};

class WildCat : public Cat {
public:
    // Overwrites Cat sound method
    std::string sound() const {
        return std::string("Rarr");
    }

};

class Dog : public IAnimal{
public:
    // Implements deleted method
    std::string sound() const {
        return std::string("Wuff");
    }
};


class Car {
public:
    // Implements deleted method
    std::string sound() const {
        return std::string("Brum");
    }
};



// Sfinae tests for proper inheritance
template<class TAnimal,
         typename = std::enable_if_t<std::is_base_of<IAnimal, TAnimal>::value> >
void listenTo(TAnimal const & a ) {
    std::cout << a.sound() << std::endl;
}


int main(){

    // Objects of type IAnimal can not be instanciated
    // IAnimal a;

    // Cats and Dogs behave like IAnimals
    Cat cat;
    WildCat wildCat;
    Dog dog;
    Car car;

    listenTo(cat);
    listenTo(wildCat);
    listenTo(dog);

    // A car is no animal -> compile time error
    // listenTo(car);

    return 0;
}

最佳答案

C++ 还没有 Concepts :-( 但 gcc-6 实现了它:

template <class T>
concept bool Animal() { 
    return requires(const T& a) {
        {a.sound()} -> std::string;
    };
}

void listenTo(const Animal& animal) {
    std::cout << animal.sound() << std::endl;
}

Demo

但是您可以使用 is-detected 相对轻松地创建特征:

typename <typename T>
using sound_type = decltype(std::declval<const T&>().sound());

template <typename T>
using has_sound = is_detected<sound_type, T>;

template <typename T>
using is_animal = has_sound<T>;
// or std::conditional_t<has_sound<T>::value /*&& other_conditions*/,
//                       std::true_type, std::false_type>;

然后是常规的 SFINAE:

template<class T>
std::enable_if_t<is_animal<T>::value>
listenTo(const T& animal) {
    std::cout << animal.sound() << std::endl;
}

关于c++ - 使用=delete 进行接口(interface)描述,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39622051/

相关文章:

c++ - 处理 float 不准确

c++ - std::array 模板实例会占用更多代码内存吗?

c++ - 如何处理静态存储时长警告?

c++ - 消除函数指针和指向类实例的指针之间的歧义

c++ - 是否可以将模板专门用于语言链接?

c++ - 数据何时在 SSE 寄存器和堆栈之间移动?

c++ - OpenCV 视频采集 API

c++ - 用于 C++ 应用程序的 GUI 测试工具

c++ - 为什么这个 lambda 可以流式传输?

c++ - 使用 SFINAE 在 C++ 中强制类型转换