gpt4 book ai didi

c++ - 如何在尝试为某些非类型值实例化模板子类方法时产生编译器错误?

转载 作者:行者123 更新时间:2023-11-30 02:27:34 25 4
gpt4 key购买 nike

如果使用程序为某个模板参数调用非类型模板类方法,我想生成一个编译器错误。

typedef SubWithTemplate<1> SubWithTemplate1;
typedef SubWithTemplate<2> SubWithTemplate2;

SubWithTemplate1 &subWithTemplate1 = SubWithTemplate1::instance;
SubWithTemplate2 &subWithTemplate2 = SubWithTemplate2::instance;

subWithTemplate1.doSomething(); // Should compile OK
subWithTemplate1.doSomethingElse(); // Should compile OK
subWithTemplate2.doSomething(); // Should NOT compile OK
subWithTemplate2.doSomethingElse(); // Should compile OK

我的起点是以下两个类:

super .h:

class Super {
protected:
Super() {}
public:
virtual void doSomething();
void doSomethingElse();
};

super .cpp:

void Super::doSomething() {}
void Super::doSomethingElse() {}

SubWithTemplate.h:

template<int SUBNUMBER>
class SubWithTemplate : public Super {

public:
static SubWithTemplate<SUBNUMBER> instance;
void doSomething() {
// Do something
};

private:
SubWithTemplate() : Super() {}
};

template<int SUBNUMBER>
SubWithTemplate<SUBNUMBER> SubWithTemplate<SUBNUMBER>::instance;

我对 Boost 或 mpl 不是很流利,但我有一些模糊的感觉 BOOST_MPL_ASSERT 可以给我带来一些成功。但我无法理解其中的本质。

我试过类似的方法:

SubWithTemplate.h:

...
void doSomething() {
BOOST_MPL_ASSERT_MSG(<some test on SUBNUMBER being different from 2 and 7 and less than 25>, <what here?>, <what here?> )
};
...

我不希望 Super 被模板化,因为它应该是所有子类的相同实例。

如果我可以避免在 doSomething 上使用 virtual,那就更好了。

如果有比我更专业的人能帮助我,我将不胜感激。

最佳答案

这不是一个很好的解决方案,但是...如果您可以使用 C++11,禁用 doSomething() 怎么样?通过 SFINAE?

在以下示例中 doSomething()SUBNUMBER 的所有值启用除了 2

#include <type_traits>

class Super
{
protected:
Super () {}
void doSomething () {}

public:
void doSomethingElse () {}
};

template <int SUBNUMBER>
class SubWithTemplate : public Super
{
public:
static SubWithTemplate<SUBNUMBER> instance;

template <int I = SUBNUMBER>
typename std::enable_if<I!=2>::type doSomething ()
{ Super::doSomething(); }

private:
SubWithTemplate () : Super() {}
};

template<int SUBNUMBER>
SubWithTemplate<SUBNUMBER> SubWithTemplate<SUBNUMBER>::instance;

typedef SubWithTemplate<1> SubWithTemplate1;
typedef SubWithTemplate<2> SubWithTemplate2;

int main()
{
SubWithTemplate1 &subWithTemplate1 = SubWithTemplate1::instance;
SubWithTemplate2 &subWithTemplate2 = SubWithTemplate2::instance;

subWithTemplate1.doSomething(); // OK
subWithTemplate1.doSomethingElse(); // OK
//subWithTemplate2.doSomething(); // compilation error
subWithTemplate2.doSomethingElse(); // OK
}

--- 编辑 ---

正如 Guillaume Racicot 所指出的(谢谢!)这个解决方案可以通过显式模板值来规避(I = SUBNUMBER 只是一个默认值)。

如果

subWithTemplate2.doSomething();

给出一个编译错误(按照 OP 的要求),

subWithTemplate2.doSomething<1>();

编译没有问题。

为了避免这种情况,我可以提出几个解决方案。

(1) 你可以添加一个static_assert() , 在函数体中,强加 I == SUBNUMBER ;像

    template <int I = SUBNUMBER>
typename std::enable_if<I!=2>::type doSomething ()
{
static_assert(I == SUBNUMBER, "I != SUBNUMBER; this in wrong");
Super::doSomething();
}

(2) 按照 Guillaume Racicot 的建议(再次感谢!),您可以整合 I == SUBNUMBERstd::enable_if<>测试;像

    template <int I = SUBNUMBER>
typename std::enable_if<(I!=2) && (I == SUBNUMBER)>::type
doSomething ()
{ Super::doSomething(); }

我发现第二种解决方案更优雅一些,但我不是专家,对我来说,这是一个品味问题。

--- 编辑 2 ---

how could I prevent the SubWithTemplate class from being instantiated unless the SUBNUMBER is within a given interval?

防止全类火爆?不仅是 doSomething()方法?

我想到的第一个方法是使用 static_alert() .

例如,如果您只想获得许可 SUBNUMBER s在[5,10[(含5,不含10)范围内,可以按如下方式编写构造函数。

SubWithTemplate () : Super()
{ static_assert((SUBNUMBER >= 5) && (SUBNUMBER < 10), "error message"); }

但我想还有其他方法。

--- 编辑 3 ---

另一种防止 SubWithTemplate 类被实例化的方法,除非 SUBNUMBER 在给定的时间间隔内。

一种在 C++98 中也适用的方法。

它基于默认特化和模板默认值。

class Super
{
protected:
Super () {}
void doSomething () {}

public:
void doSomethingElse () {}
};

template<bool b> struct boolWrapper {};

template <int I, bool = (I >= 0) && (I <= 20)>
struct rangeLimit;

template <int I>
struct rangeLimit<I, true>
{ };

template <int SUBNUMBER>
class SubWithTemplate : public Super, public rangeLimit<SUBNUMBER>
{
public:
static SubWithTemplate<SUBNUMBER> instance;

void doSomething ()
{ Super::doSomething(); }

private:
SubWithTemplate () : Super() {}
};

template<int SUBNUMBER>
SubWithTemplate<SUBNUMBER> SubWithTemplate<SUBNUMBER>::instance;

typedef SubWithTemplate<1> SubWithTemplate1;
typedef SubWithTemplate<2> SubWithTemplate2;
typedef SubWithTemplate<20> SubWithTemplate20;
//typedef SubWithTemplate<21> SubWithTemplate21; compilation error

int main()
{
}

关于c++ - 如何在尝试为某些非类型值实例化模板子类方法时产生编译器错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41539005/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com