在C#中,我们可以定义一个泛型类型,它对可用作泛型参数的类型施加约束。以下示例说明了通用约束的用法:

interface IFoo
{
}


class Foo<T> where T : IFoo
{
}

class Bar : IFoo
{
}

class Simpson
{
}

class Program
{
    static void Main(string[] args)
    {
        Foo<Bar> a = new Foo<Bar>();
        Foo<Simpson> b = new Foo<Simpson>(); // error CS0309
    }
}

有没有办法可以在C ++中对模板参数施加约束。


C ++ 0x对此有本机支持,但我在谈论当前的标准C ++。

有帮助吗?

解决方案

正如其他人所提到的,C ++ 0x正在将此内置于该语言中。在那之前,我建议 Bjarne Stroustrup 模板约束建议

编辑: Boost 也有替代它自己的

Edit2:看起来像概念已从C ++ 0x中删除

其他提示

如果您使用C ++ 11,则可以将 static_assert std :: is_base_of 一起用于此目的。

例如,

#include <type_traits>

template<typename T>
class YourClass {

    YourClass() {
        // Compile-time check
        static_assert(std::is_base_of<BaseClass, T>::value, "type parameter of this class must derive from BaseClass");

        // ...
    }
}

&QUOT;隐&QUOT;是正确的答案。模板有效地创建了“鸭子打字”。场景,由于它们的编译方式。您可以在模板类型值上调用所需的任何函数,并且唯一可以接受的实例是为其定义该方法的实例。例如:

template <class T>
int compute_length(T *value)
{
    return value->length();
}

我们可以在指向任何声明 length()方法的类型的指针上调用此方法,以返回 int 。正是如此:

string s = "test";
vector<int> vec;
int i = 0;

compute_length(&s);
compute_length(&vec);

...但不是指向声明 length()的类型的指针:

compute_length(&i);

第三个例子不会编译。

这是有效的,因为C ++为每个实例化编译了一个新版本的模板化函数(或类)。当它执行该编译时,它在类型检查之前将模板实例化直接,几乎像宏一样替换到代码中。如果一切仍然适用于该模板,则编译继续进行,我们最终得出结果。如果有任何失败(比如 int * 没有声明 length()),那么我们就会得到可怕的六页模板编译错误。

你可以在IFoo上放一个什么都不做的保护类型,确保它在Foo的T上有:

class IFoo
{
public:
    typedef int IsDerivedFromIFoo;
};

template <typename T>
class Foo<T>
{
    typedef typename T::IsDerivedFromIFoo IFooGuard;
}

查看 Boost

  

Boost概念检查库(BCCL)

     

概念检查库允许添加显式语句并检查概念采用提议的C ++语言扩展的风格。

排序。如果你static_cast到IFoo *,那么除非调用者传递一个可以分配给IFoo *的类,否则将无法实例化模板。

仅隐含。
您在实际调用的方法中使用的任何方法都强加于模板参数。

你可以做到。创建基本模板。使它只有私有构造函数。然后为您想要允许的每个案例创建特化(或者如果不允许的列表比允许的列表小得多,则相反)。

编译器不允许您实例化使用私有构造函数的模板。

此示例仅允许使用int和float进行实例化。

template<class t> class FOO { private: FOO(){}};

template<> class FOO<int>{public: FOO(){}};

template<> class FOO<float>{public: FOO(){}};

它不是一种简短而优雅的方式,但它可能。

查看CRTP模式(奇怪的递归模板模式)。它旨在帮助支持静态继承。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top