首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >由于继承,operator<<()不能从模板解析

由于继承,operator<<()不能从模板解析
EN

Stack Overflow用户
提问于 2019-06-19 03:51:51
回答 4查看 85关注 0票数 -1

我正在使用一组类,我的主要代码如下所示:

main.cpp

#include "calc.h"

int main() {
    neg_inf nif;
    pos_inf pif;

    limit<double, infinity> l( 3.4, nif, pif, 2.2 )

    std::cout << "value dx  = " << l.value() << '\n'
              << "lower lim = " << l.lower() << '\n'
              << "upper lim = " << l.upper() << '\n'
              << "step_size = " << l.step() << '\n';

    return EXIT_SUCCESS;
}

预期输出应为:

value dx  = 3.4
lower lim = -inf
upper lim = inf
step_size = 2.2

以下是我的类:

calc.h

#pragma once

#include <cmath>
#include <iostream>
#include <limits>
#include <type_traits> 

struct infinity {
protected:
    infinity() = default;
};

struct pos_inf : public infinity {
    constexpr double operator()() { return std::numeric_limits<double>::infinity(); }
};

struct neg_inf : public infinity {
   constexpr double operator()() { return -std::numeric_limits<double>::infinity(); }
};

std::ostream& operator<<( std::ostream& os, const pos_inf& inf );
std::ostream& operator<<( std::ostream& os, const neg_inf& inf );

template<typename dX, class bound>
class limit {
    dX dx;
    bound lowerBound;
    bound upperBound;
    double step_size;

public:
    limit( dX x, bound lower, bound upper, double step = 1 ) :
        dx{ x }, lowerBound{ lower }, upperBound { upper }, step_size { step }
    {}

    dX value() const { return dx; }
    bound lower() const { return lowerBound; }
    bound upper() const { return upperBound; }
    double step() const { return step_size; }
};

calc.cpp

#include "calc.h"

std::ostream& operator<<( std::ostream& os, const pos_inf& inf ) {
    // originally intended to do:
    // return os << inf(); // but fails to compile

    auto v = pos_inf()(); // this works
    return os << v;
}

std::ostream& operator<<( std::ostream& os, const neg_inf& inf ) {
    // same as above...

    auto v = neg_inf()();
    return os << v;
}

然而,在main.cpp Visual Studio2017中生成了这个编译器错误:

c:\***\main.cpp(33): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'bound' (or there is no acceptable conversion)
1>        with
1>        [
1>            bound=infinity
1>        ]

基于这行代码:

<< "lower lim = " << l.lower() << '\n'

并在l.lower()中失败

但是,如果我在main中执行此操作:

#include "calc.h"

int main() {
    neg_inf nif;
    pos_inf pif;

    std::cout << nif << '\n' << pif << '\n'

    return EXIT_SUCCESS;
}

我正在获取输出:

-inf
inf

这告诉我,我的operator<<()适用于继承的结构,但是当我将它的父类型作为模板参数传递并将派生类型传递到limit类的构造函数中时,operator<<()不能解析。这似乎是一个模棱两可的问题,但我不确定如何解决这个问题。我在这里遗漏或忽略了什么?

顺便说一句,有没有更优雅的方式来表示-/+inf呢?我在这里使用继承,因为+- inf不是数字,而是一个概念,它们彼此相似,但指向不同的方向。因此,当我将无穷大类型作为模板参数传递时,我希望能够将下限设置为-inf,将上限设置为+inf。我希望绑定类型是一个模板,因为我可能想要使用整数界限或双精度界限,例如,在[-1,1][0.0,1.0]之间,这些都是数值界限。我不知道如何用更优雅的方式表达无穷大,任何提示或建议都将不胜感激。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-06-19 04:20:51

我认为你对自己的约束太多了:你可以删除基类,为pos_infneg_inf添加operator<<,并为limit添加额外的类型,这样你就可以拥有不同类型的两个界限。我的意思是:

Calc.h

#pragma once

#include <cmath>
#include <iostream>
#include <limits>
#include <type_traits> 


struct pos_inf {
    constexpr double operator()() const { return std::numeric_limits<double>::infinity(); }
};

struct neg_inf  {
    constexpr double operator()() const { return -std::numeric_limits<double>::infinity(); }
};
// Both operators defined
std::ostream& operator<<(std::ostream& os, const pos_inf& inf);
std::ostream& operator<<(std::ostream& os, const neg_inf& inf);

//extra template type  in limit
template<typename dX, class lowerBoundType, class UpperBoundType>
class limit {
    dX dx;
    lowerBoundType lowerBound;
    UpperBoundType upperBound;
    double step_size;

public:
    limit(dX x, lowerBoundType lower, UpperBoundType upper, double step = 1) :
        dx{ x }, lowerBound{ lower }, upperBound{ upper }, step_size{ step }
    {}

    dX value() const { return dx; }
    lowerBoundType lower() const { return lowerBound; }
    UpperBoundType upper() const { return upperBound; }
    double step() const { return step_size; }
};

Calc.cpp

#include "calc.h"

std::ostream& operator<<(std::ostream& os, const pos_inf& inf) {
    return os << inf(); // but fails to compile

}

std::ostream& operator<<(std::ostream& os, const neg_inf& inf) {
    return os << inf(); // but fails to compile

}

main.cpp

#include "calc.h"

int main() {
    neg_inf nif;
    pos_inf pif;

    limit<double, neg_inf, pos_inf> l(3.4, nif, pif, 2.2);

        std::cout << "value dx  = " << l.value() << '\n';
        std::cout << "lower lim = " << l.lower() << '\n';
        std::cout << "upper lim = " << l.upper() << '\n';
        std::cout << "step_size = " << l.step() << '\n';

    return EXIT_SUCCESS;
}

如果这不是你想要的,我道歉。

票数 1
EN

Stack Overflow用户

发布于 2019-06-19 04:06:12

好的,您已经使用const pos_inf& infconst neg_inf& infoperator<<进行了重载,但是您使用infinity作为模板类型,因此您的lower()方法返回infinity。当然,您的运算符重载不会被使用,因为它们是从infinity派生的类型。为什么不直接重载infinityoperator<<呢?

一些快速的想法如何解决这个问题:

  1. 使double operator()()虚拟化。但是您不能将其与用于limitsconstexpr.
  2. Using template<typename dX, class lower_bound, class upper_bound>类混合在一起来实际指定这两个边界的类型,然后您的lowerupper方法可以返回pos_infneg_inf类型,并且您当前的运算符将起作用。此外,为了简单起见,如果类型不总是不同,您也可以将第二个类型默认为第一个类型- template<typename dX, class lower_bound, class upper_bound = lower_bound>.
  3. After提供了更多关于设计的信息-那么为什么不真正地将infinity类模板化(既然我假设您希望它与dX匹配,并在那里实现限制?

#include #include > template struct infinity { public: infinity() = default;constexpr double lower() { return -std::numeric_limits::infinity();} constexpr double std::numeric_limits::infinity(){ return std::numeric_limits::infinity();} };模板类限制{ dX dx;double step_size;dX : limit(dX x,double step = 1):dx{ x },step_size{ step } {} dX value() const { dX dx;}dX lower() const { return infinity().lower();}dX upper() const { return infinity().upper();} double step() const {dX step_size;} };int main() { limit l(3.4,2.2);std::cout << "value dx =“<< l.value() << '\n‘<<”下lim =“<< l.lower() << '\n’<<”上lim =“<< l.upper() << '\n‘<< "step_size =”<< l.step() << '\n';return EXIT_SUCCESS;}Making return。这样,您实际上将从绑定类型到所需值类型的解析保留在模板中,并且您可以混合无限和非无限限制。

#include #include > struct pos_inf { constexpr operator double() const { return std::numeric_limits::infinity();} };struct neg_inf { constexpr operator double() const { return -std::numeric_limits::infinity();} };template类限制{ dX dx;upper_bound lowerBound;lower_bound upperBound;double step_size;dX : limit(dX x,upper_bound lower,lower_bound upper,double step = 1):dx{ x },lowerBound{ lower },upperBound{ upper },step_size{ step } {} //对于无穷大,这两个函数将调用运算符double(),对于实际的double,它将返回固定值dX lower() const {upper_bound lowerBound;} dX upper() const {lower_bound upperBound;}dx value() const { return dx;} double step() const { return step_size;} };int main() { limit l(3.4,pos_inf(),neg_inf(),2.2);//无限限制l2(3.4,1,5,2.2);//固定值std::cout << "value dx =“<< l.value() << '\n‘<<”下lim =“<< l.lower() << '\n’<<”上lim =“<< l.upper() << '\n‘<< "step_size =”<< l.step() << '\n';return EXIT_SUCCESS;}

票数 2
EN

Stack Overflow用户

发布于 2019-06-19 04:20:11

不要那样重载子类的运算符。使用虚方法进行输出,并将泛型类型与调用虚方法的重载运算符一起使用:

class infinity {
  public:
    virtual ostream &printTo(ostream &o) const = 0;
};
ostream &operator<<(ostream &o,const infinity &i) {
  return i.printTo(o);
}
class neg_inf : public infinity {
  public:
    virtual ostream &printTo(ostream &o) const {
        // do what you want
        return o;
    }
};
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56656139

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档