模板约束 C++

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/122316/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:01:57  来源:igfitidea点击:

Template Constraints C++

c++templatesconstraints

提问by Jorge Ferreira

In C# we can define a generic type that imposes constraints on the types that can be used as the generic parameter. The following example illustrates the usage of generic constraints:

在 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
    }
}

Is there a way we can impose constraints for template parameters in C++.

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



C++0x has native support for this but I am talking about current standard C++.

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

采纳答案by luke

As someone else has mentioned, C++0x is getting this built into the language. Until then, I'd recommend Bjarne Stroustrup's suggestions for template constraints.

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

Edit: Boostalso has an alternative of its own.

编辑:Boost也有自己的.

Edit2: Looks like concepts have been removed from C++0x.

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

回答by Venemo

If you use C++11, you can use static_assertwith std::is_base_offor this purpose.

如果您使用 C++11,则可以为此目的使用static_assertwith std::is_base_of

For example,

例如,

#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");

        // ...
    }
}

回答by Daniel Spiewak

"Implicitly" is the correct answer. Templates effectively create a "duck typing" scenario, due to the way in which they are compiled. You can call any functions you want upon a template-typed value, and the only instantiations that will be accepted are those for which that method is defined. For example:

“隐含”是正确答案。由于它们的编译方式,模板有效地创建了“鸭子输入”场景。您可以在模板类型的值上调用您想要的任何函数,并且将接受的唯一实例化是定义该方法的那些实例化。例如:

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

We can call this method on a pointer to any type which declares the length()method to return an int. Thusly:

我们可以在指向任何类型的指针上调用此方法,该类型声明该length()方法返回一个int. 因此:

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

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

...but not on a pointer to a type which does notdeclare length():

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

compute_length(&i);

This third example will not compile.

第三个示例将无法编译。

This works because C++ compiles a new version of the templatized function (or class) for each instantiation. As it performs that compilation, it makes a direct, almost macro-like substitution of the template instantiation into the code prior to type-checking. If everything still works with that template, then compilation proceeds and we eventually arrive at a result. If anything fails (like int*not declaring length()), then we get the dreaded six page template compile-time error.

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

回答by Eclipse

You can put a guard type on IFoo that does nothing, make sure it's there on T in Foo:

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

class IFoo
{
public:
    typedef int IsDerivedFromIFoo;
};

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

回答by Nemanja Trifunovic

Check out Boost

查看提升

The Boost Concept Check Library (BCCL)

The Concept Check library allows one to add explicit statement and checking of conceptsin the style of the proposed C++ language extension.

Boost 概念检查库 (BCCL)

概念检查库允许以提议的 C++ 语言扩展的风格添加明确的声明和概念检查。

回答by Lou Franco

Sort of. If you static_cast to an IFoo*, then it will be impossible to instantiate the template unless the caller passes a class that can be assigned to an IFoo *.

有点。如果您将 static_cast 转换为 IFoo*,则除非调用方传递可以分配给 IFoo * 的类,否则将无法实例化模板。

回答by shoosh

Only implicitly.
Any method you use in a method that is actually called is imposed on the template parameter.

只是含蓄地。
您在实际调用的方法中使用的任何方法都强加在模板参数上。

回答by OldMan

You can do it. Create the base template. Make it have only Private constructors. Then create specializations for each case you want to allow (or make the opposite if the disallowed list is much smaller than the allowed list).

你能行的。创建基本模板。让它只有私有构造函数。然后为您想要允许的每种情况创建专门化(或者如果不允许的列表比允许的列表小得多,则进行相反的操作)。

The compiler will not allow you to instantiate the templates that use the version with private constructors.

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

This example only allow instantiation with int and float.

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

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

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

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

Its not a short and elegant way of doing it, but its possible.

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

回答by OldMan

Look at the CRTP pattern (Curiously Recursive Template Pattern). It is designed to help support static inheritence.

看一下 CRTP 模式(Curious Recursive Template Pattern)。它旨在帮助支持静态继承。