确保C 模板不会与缺少功能进行编译

Ensuring C++ template does not compile with missing functions

本文关键字:功能 编译 确保      更新时间:2023-10-16

我有一个模板类template<typename T> Foo使用T的某些功能。但是,事实证明,即使没有T具有所有必要的成员功能,代码也可以编译。一个例子如下。

template<class T>
struct Foo {
    T t;
    int foo() {
        return t.foo();
    }
    int bar() {
        return t.bar();
    }
};
struct baz {
    int foo() {
        return 42;
    }
};
int main() {
    Foo<baz> x;
    return x.foo();
}

如果T不提供所有必要的功能,我该如何确保代码不编译?我知道,如果我使用包含所有继承并从中得出的基类,则可以做到这一点。但是,如果可以使用模板没有太多其他代码,我将非常感谢。

我在Linux上使用GCC 4.8.2。

为了要求类型是具有某些可访问成员功能的类类型,只需参考它们即可。例如。在Foo的每个构造函数中,您可以说

Foo()
{
    (void) sizeof( decltype( t.foo() ) );
    (void) sizeof( decltype( t.bar() ) );
}

上面的示例比示例所需的要多一些,但是显示了如何轻松确保具有某些参数或具有某些签名的功能。

或者您可以将这些表达式放在static_assert中。

类似于@cheers的答案,但是有点通用(即使Foo不包含T):

template<typename...>
struct test {};
template<typename T>
using Foo_test = test<
    decltype(std::declval<T>().foo()),
    decltype(std::declval<T>().bar())
>;
template<class T>
struct Foo : Foo_test<T> {
    // ...
};

此问题与目前为C 14设计的概念有关,因此将来可能会更方便。

使用您的代码,我只需使用static_assertstd::is_member_function_pointer如下(在此处文档)

template<class T>
struct Foo {
    static_assert(std::is_member_function_pointer<decltype(&T::foo)>::value, "");
    static_assert(std::is_member_function_pointer<decltype(&T::bar)>::value, "");
    T t;
    int foo() {
        return t.foo();
    }
    int bar() {
        return t.bar();
    }
};
struct baz {
    int foo() {
        return 42;
    }
};
int main() {
    Foo<baz> x;
    return x.foo();
}