Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/124.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.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++中,我有一些类妈妈< /代码>。我知道我可以创建一个接受任何类的模板函数,如: template <class T> void Iacceptanything(T x) { // Do something }_C++_Templates_Inheritance - Fatal编程技术网

只接受某类继承人的模板函数 在C++中,我有一些类妈妈< /代码>。我知道我可以创建一个接受任何类的模板函数,如: template <class T> void Iacceptanything(T x) { // Do something }

只接受某类继承人的模板函数 在C++中,我有一些类妈妈< /代码>。我知道我可以创建一个接受任何类的模板函数,如: template <class T> void Iacceptanything(T x) { // Do something },c++,templates,inheritance,C++,Templates,Inheritance,这可能吗?如果和std::是的基础,则使用std::enable #include <type_traits> #include <iostream> class Base { }; class Derived : public Base { }; class NotDerived { }; // If the return type of foo() is not void, add where indicated. template <typename T&

这可能吗?

如果
std::是
的基础,则使用
std::enable

#include <type_traits>
#include <iostream>

class Base { };
class Derived : public Base { };
class NotDerived { };

// If the return type of foo() is not void, add where indicated.
template <typename T>
typename std::enable_if<std::is_base_of<Base, T>::value /*, some_type*/>::type
foo(T) {
    std::cout << "Derived from Base." << std::endl;
}

// If the return type of foo() is not void, add where indicated.
template <typename T>
typename std::enable_if<!std::is_base_of<Base, T>::value /*, some_type*/>::type
foo(T) {
    std::cout << "Not derived from Base." << std::endl;
}

int
main() {
    Derived d;
    NotDerived nd;

    foo(d);
    foo(nd);
}
#包括
#包括
类基{};
派生类:公共基{};
类NotDerived{};
//如果foo()的返回类型不是void,请在指定的位置添加。
模板
typename std::enable_if::type
傅(T){

std::cout使用
std::enable\u如果
std::是
的基础,如下所示:

template <typename T, typename = enable_if<is_base_of<mom, T>::value>::type>
void Iacceptonlysonsofmom(T x)
{
}
模板
void iaceptonlysonsofmom(tx)
{
}

如果不能使用
C++11
,可以使用Boost的
enable_If_C
is_base_of
实现同样的功能。在上述代码中,您需要将
enable_If
替换为
enable_If_C
,并确保使用适当的名称空间。

正如其他人建议的那样,您可以使用
enable_If
但它也可能有问题。它在编译器中可能很脆弱,如果处理不当,可能会导致ODR出现问题,可能会与从其他作用域(ADL)中拉入的函数发生冲突,并且可能不是最佳选择

您确实有两种选择,它们不那么易变,可能使代码更易于理解和维护。一种选择(如注释中所述)是使用和。这是目前为止(IMHO)最简单的解决方案。这种方法允许您维护函数的单个实现,并在类型不是基
Mom
或其派生类型时强制编译时失败

#include <type_traits>

struct Mom { };
struct Child : Mom { };
struct Uncle { };

template <typename T>
void AcceptOnlyMomAndChildren(T)
{
    static_assert(std::is_base_of<Mom, T>::value, "Not derived from Base.");
}

int main()
{
    Child child;
    Uncle uncle;

    AcceptOnlyMomAndChildren(child);
    AcceptOnlyMomAndChildren(uncle);    //  Fails
}

在上面的示例中,用于指定附加参数的类型,以确定调用
Func
的哪个实现。如有必要,您可以用自己的类型特征方案替换它以支持附加实现。

您可以使用
std::enable\u if
static\u assert()
对于这一点,我建议不要限制模板参数;如果您使用依赖于
mom
的某些功能,那么模板将无法与其他对象实例化(除非它们提供兼容的接口——如果它们提供了兼容的接口,那么为什么会对您产生任何影响?),但如果不这样做,则没有理由将其限制为仅在
mom
对象上工作。您可以删除
std::enable_if
的显式第二个参数,因为它默认为
void
#include <type_traits>

struct Mom { };
struct Child : Mom { };
struct Uncle { };

template <typename T>
void AcceptOnlyMomAndChildren(T)
{
    static_assert(std::is_base_of<Mom, T>::value, "Not derived from Base.");
}

int main()
{
    Child child;
    Uncle uncle;

    AcceptOnlyMomAndChildren(child);
    AcceptOnlyMomAndChildren(uncle);    //  Fails
}
#include <type_traits>
#include <iostream>

struct Mom { };
struct Child : Mom { };
struct Uncle { };

template <typename T>
void Func(T&, std::true_type)
{
    std::cout << "Derived from Base." << std::endl;
}

template <typename T>
void Func(T&, std::false_type)
{
    std::cout << "Not derived from Base." << std::endl;
}

template <typename T>
void Func(T& arg)
{
    Func(
        arg,
        typename std::conditional<
            std::is_base_of<Mom, T>::value,
            std::true_type, std::false_type>::type());
}


int main()
{
    Child child;
    Uncle uncle;

    Func(child);
    Func(uncle);
}