Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;模板限制_C++_Templates - Fatal编程技术网

C++ C++;模板限制

C++ C++;模板限制,c++,templates,C++,Templates,我想知道有没有办法对模板类设置限制? 指定模板中替换的每个类型都必须有特定的祖先(实现某些接口) 您可以使用或类似的库来声明对模板参数的限制 例如: #include <limits> #include <boost/static_assert.hpp> template <class UnsignedInt> class myclass { private: BOOST_STATIC_ASSERT((std::numeric_limits<Un

我想知道有没有办法对模板类设置限制?
指定模板中替换的每个类型都必须有特定的祖先(实现某些接口)

您可以使用或类似的库来声明对模板参数的限制

例如:

#include <limits>
#include <boost/static_assert.hpp>

template <class UnsignedInt>
class myclass
{
private:
   BOOST_STATIC_ASSERT((std::numeric_limits<UnsignedInt>::digits >= 16)
                        && std::numeric_limits<UnsignedInt>::is_specialized
                        && std::numeric_limits<UnsignedInt>::is_integer
                        && !std::numeric_limits<UnsignedInt>::is_signed);
public:
   /* details here */
};
#包括
#包括
模板
类myclass
{
私人:
BOOST\u STATIC\u ASSERT((标准::数字限制::数字>=16)
&&标准::数值限制::是否专用
&&标准::数值限制::是整数
&&!std::数值限制::有符号);
公众:
/*这里的细节*/
};
编辑:例如,您可以编写

template < class B >
class A {
    BOOST_STATIC_ASSERT(boost::is_base_of<C, B>);

public:
    B * obj;
    int f() {
        return B::x + this->obj->f();
    }
};
模板
甲级{
BOOST_STATIC_ASSERT(BOOST::is_base_of);
公众:
B*obj;
int f(){
返回B::x+this->obj->f();
}
};

您可以使用这样的技巧(如果您不想使用Boost):

类基
{
公众:
静态常量int模板需要基本类=0;
};
类正确:公共基
{
};
类别不正确
{
};
模板
TMPL类
{
静态常量int TEMPLATE_REQUIRES_BASE_CLASS=T::TEMPLATE_REQUIRES_BASE_CLASS;
T*m\T;
};
void main()
{
tmplone;//好的
tmpltwo;//将不编译
}
第一行将编译。第二个将不编译,并将出现以下错误:

test.cpp
test.cpp(18) : error C2039: 'TEMPLATE_REQUIRES_BASE_CLASS' : is not a member of 'Incorrect'
        test.cpp(12) : see declaration of 'Incorrect'
        test.cpp(25) : see reference to class template instantiation 'TMPL<T>' being compiled
        with
        [
            T=Incorrect
        ]
test.cpp(18) : error C2065: 'TEMPLATE_REQUIRES_BASE_CLASS' : undeclared identifier
test.cpp(18) : error C2057: expected constant expression
test.cpp
test.cpp(18):错误C2039:“模板\u需要\u基类”:不是“不正确”的成员
测试cpp(12):见“不正确”声明
cpp(25):请参阅对正在编译的类模板实例化“TMPL”的引用
具有
[
T=不正确
]
test.cpp(18):错误C2065:“模板\u需要\u基类”:未声明的标识符
test.cpp(18):错误C2057:预期的常量表达式

<代码>未来的C++版本将使用概念(这并没有将其转化为C++ 11)来支持这个。 解决此问题的一种方法是对虚拟模板参数进行专门化:

class C {};
template <class B, class dummy=void>
class A;

template <class B>
class A<B, typename enable_if<is_base_and_derived<C, B> >::type>
{
    // class definition here
};

struct D : C {};

A<D> d;     // fine
A<int> n;   // compile error - undefined class A<B>
C类{};
模板
甲级;
模板
甲级
{
//这里的类定义
};
结构D:C{};
A d;//好的
A n;//编译错误-未定义的类A

我已经给出了<>代码> Enable的独立定义,如果和 iSaseBaseION和派生的 .

模板是C++中的一种鸭式输入。 如果类支持模板使用的所有内容,则可以将其用作模板参数,否则不能

如果您的模板中有

C *instance;

void foo(T *t)
{
  instance = t;
}

然后,您强制要求T是从C派生的(或者至少是与指针兼容的赋值)

以下内容在VC10中使用静态断言。我刚刚看到过这种用法,并没有深入了解static_assert的实际功能——也许其他人可以回答这个问题

#include <type_traits>

class Base
{

};

class Derived : public Base
{

};

class SomeRandomClass
{

};

template<typename T>
class A
{
    static_assert(std::tr1::is_base_of<Base, T>::value, "T not derived from Base");
};



int _tmain(int argc, _TCHAR* argv[])
{
    argc; argv;  

    //
    //  This will compile
    A<Derived> a;

    //
    //  This will throw a compilation error
    A<SomeRandomClass> b; 

    return 0;
}
#包括
阶级基础
{
};
派生类:公共基
{
};
课堂
{
};
模板
甲级
{
静态断言(std::tr1::is_base_of::value,“T不是从base派生的”);
};
int _tmain(int argc,_TCHAR*argv[]
{
argc;argv;
//
//这将编译
A A;
//
//这将引发编译错误
A b;
返回0;
}
编译器输出为:

1>d:\temp\aaa\aaa\aaa.cpp(25): error C2338: T not derived from Base
1>          d:\temp\aaa\aaa\aaa.cpp(41) : see reference to class template instantiation 'A<T>' being compiled
1>          with
1>          [
1>              T=SomeRandomClass
1>          ]
1>d:\temp\aaa\aaa\aaa.cpp(25):错误C2338:T不是从基
1> d:\temp\aaa\aaa\aaa.cpp(41):请参阅对正在编译的类模板实例化“A”的引用
1> 与
1>          [
1> T=某个随机类
1>          ]

为什么您认为您需要这个?sooooo的可能重复不是初学者的问题:-)。这段代码在g++4.4下并没有失败,原因不明。一般来说,我会说在这种情况下,通常使用枚举:枚举{TEMPLATE_REQUIRES_BASE_CLASS=0};这还有一个额外的好处,就是在g++@Semen下,GCC不符合预期。该标准要求在隐式实例化类时实例化数据成员的声明,并且类内初始值设定项是声明的一部分,而不是声明的定义。然而,该标准有点不清楚,它说“静态数据成员的初始化(以及任何相关的副作用)不会发生,除非静态数据成员本身的使用方式要求静态数据成员的定义存在。”-然而,该规则似乎只适用于类外初始值设定项(否则就没有意义了)@Johannes:谢谢你的解释,当它建得很好的时候,我还以为我疯了……但我想enum的使用更简单。(我只是跟着Vandervourde:)
C *instance;

void foo(T *t)
{
  instance = t;
}
#include <type_traits>

class Base
{

};

class Derived : public Base
{

};

class SomeRandomClass
{

};

template<typename T>
class A
{
    static_assert(std::tr1::is_base_of<Base, T>::value, "T not derived from Base");
};



int _tmain(int argc, _TCHAR* argv[])
{
    argc; argv;  

    //
    //  This will compile
    A<Derived> a;

    //
    //  This will throw a compilation error
    A<SomeRandomClass> b; 

    return 0;
}
1>d:\temp\aaa\aaa\aaa.cpp(25): error C2338: T not derived from Base
1>          d:\temp\aaa\aaa\aaa.cpp(41) : see reference to class template instantiation 'A<T>' being compiled
1>          with
1>          [
1>              T=SomeRandomClass
1>          ]