【问题标题】:C++ templates which infer class members推断类成员的 C++ 模板
【发布时间】:2012-06-13 09:38:03
【问题描述】:

我知道我可以使用模板来假设模板使用的某些类具有某些成员变量;但是,我想知道是否有一种方法可以显式声明模板类必须具有某个成员变量或函数?

我说的是这样的例子:

template <typename T>
class Assume
{
    int value;
    Assume(T* object) : value(T->AssumedMember) {};
};


class A
{
    int AssumedMember;
    A(int val) : AssumedMember(val) {};
};


int main()
{
    A* a = new A(5);
    Assume<A> assumer(a);
    return 0;
}

我知道,至少对于 MSVC++ 中使用的编译器,类似于此示例的内容应该可以毫无问题地编译;

我只是想知道是否有一种方法可以声明,对于模板或类的使用,来自类型名 T 的 T 具有成员变量 AssumedMember。到目前为止,真正理解 Assume 仅在与具有正确必需成员(变量、函数或运算符)的类一起使用时才有效的唯一方法,要么必须编译并查看给定的编译器错误,要么自己通读整个模板,以确定是否使用了尚未定义的任何额外内容。

(另外,在不相关的说明中,有没有人知道将整个声明块声明为模板的方法?好像使用类似: template &lt;typename T&gt; { /*class... member definitions, etc..*/ } 声明整个定义块以使用相同的模板?)

【问题讨论】:

  • 在 C++11 中,您可以在 C++ pretty printer 中使用成员存在特征检查,例如 has_begin_end

标签: c++ class templates declaration member


【解决方案1】:

不,除了在模板的定义中,没有办法声明模板要求。例如,您可以使用 static_asserts 将这些要求放在定义的最前面,并提供更好的错误消息。

要一次声明多个模板函数,您可以使用带有静态成员函数的模板类:

template<typename T>
struct Foo {
    static int bar(T t);
    static T baz();
};

Foo<int>::bar(1);
auto s = Foo<std::string>::baz();

但是对于任何类型的模板声明都没有通用的方法,我认为这不会为您节省太多。


用于 static_asserts 的自定义类型特征示例

我使用了一些 C++11 的东西,但也可以在 C++98 中完成

#include <type_traits>

// the custom type traits
template<typename T> struct exists : std::true_type {};

template<typename T>
struct has_value_type {
    template<typename U>
    static typename std::enable_if<exists<typename U::value_type>::value,char>::type
    Test(int);

    template<typename U> static int Test(...);
    static constexpr bool value = sizeof(Test<T>(0)) == sizeof(char);
};

template<typename T>
struct has_member_i {
    template<typename U>
    static typename std::enable_if<0!=sizeof(&U::i),char>::type Test(int);
    template<typename U> static int Test(...);
    static constexpr bool value = sizeof(Test<T>(0)) == sizeof(char);
};

// your template for which you want to declare requirements
template<typename T>
void test(T t) {
    static_assert(has_value_type<T>::value, "value_type must be a member type alias of T");
    static_assert(has_member_i<T>::value, "i must be a member variable of T");
}

// one type that meets the requirements and one that doesn't
struct Foo {
    typedef int value_type;
    int i;
};

struct Bar {};

int main() {
    test(Foo());
    test(Bar());
}

【讨论】:

  • 你知道有一种说法吗 static_assert(X is member of Y, "X needs to be a member of Y!"); ?这听起来像是一个很好的处理方式,直到下一个版本的 C++ 或其他东西。
  • 我以前从未见过以如此有趣和有用的方式使用模板。非常感谢!
  • 如果您有兴趣,模板的更强大的用途被称为“模板元编程”。您甚至可以使用它们在编译时执行完整的计算。
  • @bames52 谢谢;我真正阅读过的关于模板的所有资源都没有像这样复杂。然而,当时我也不知道“模板元编程”这个词。每天学习新东西!
  • 我最近尝试了这段代码,但我遇到了编译问题(除了预期的问题);它在尝试获取 Test(0) 的大小时声称非法 sizeof 运算符,在 has_member_i 中(但不在 has_value_type 中!)对此有什么想法吗? =/
【解决方案2】:

标准委员会一直在研究此功能,称为“概念”。但是,它并没有进入 C++11。

但是,有两个编译器可以运行它(具有各种功能)。看看ConceptGCCConceptClang

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-04
  • 2023-03-31
相关资源
最近更新 更多