确保C ++模板不会使用缺少的函数进行编译

时间:2014-03-06 01:01:21

标签: c++ templates

我有一个模板类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。

3 个答案:

答案 0 :(得分:3)

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

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

上面的内容比您的示例要多一些,但展示了如何轻松确保函数可以使用某些参数调用,或者具有某些签名。

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

答案 1 :(得分:2)

与@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设计的 concepts 有关,因此将来这些测试可能会更方便。

答案 2 :(得分:0)

使用您的代码,我只需使用static_assertstd::is_member_function_pointer,如下所示(文档here

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();
}