Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/163.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++_Friend Function - Fatal编程技术网

C++ 接受类参数的友元函数的尾部返回类型

C++ 接受类参数的友元函数的尾部返回类型,c++,friend-function,C++,Friend Function,有关以下代码: using std::string; class person { private: string fname, lname; double salary; public: person(string, string, double); // ctor declaration ~person(); // dtor declaration double operator+(person); friend auto salary_bu

有关以下代码:

using std::string;

class person
{
private:
    string fname, lname;
    double salary;
public:
    person(string, string, double); // ctor declaration
    ~person(); // dtor declaration
    double operator+(person);
    friend auto salary_burden(person x, person y) -> decltype(x+y); // salary burden of two employees
};
我在
y
下面的
decltype
中看到了一个红色的波形,Intellisense说
不能转换为不完整的类“person”

这是怎么回事


注:方法(包括系数和数据系数)的定义在不同的翻译单位中。我想这不是这里错误的原因。

问题在于,即使
decltype
的操作数可能是不完整的类型,也不适用于构成充当
decltype
操作数的prvalue的子表达式

decltype(x+y);
相当于

decltype(operator+(x, y));
但是
person
在它自己的定义中是不完整的。您可以通过将
operator+
定义为:

double operator+(person const&);

问题是,即使
decltype
的操作数可能是不完整的类型,也不适用于构成充当
decltype
操作数的prvalue的子表达式

decltype(x+y);
相当于

decltype(operator+(x, y));
但是
person
在它自己的定义中是不完整的。您可以通过将
operator+
定义为:

double operator+(person const&);

您可能会发现一些有趣的注意事项:

#include <string>
#include <iostream>

namespace humans
{
    class person
    {
    private:
        // certainly never write using namespace::thing in header files.
        // if you are going to be using a type, do it in a very confined scope, in a cpp file
        std::string fname, lname;
        double salary;

    public:
        person(std::string, std::string, double); // ctor declaration

        // you neither need or want a destructor for this class.
        // if you define a destructor, you must also define copy & assignment
        // operators. See rule of 5, 3 or none.

        // define a way to see the salary
        double get_salary() const { return salary; }

        // there is no such thing as a person plus a person.
        // avoid nonsensical mathematical abstractions
        // double operator+(person);
    };

    // let's also provide a free function to get_salary, because it can be useful in ADL
    auto get_salary(person const & p) -> decltype(p.get_salary())
    {
        return p.get_salary();
    }


    // salary_burden does not need to be a friend now that we
    // have a way to get the salary. Since there is a free function available
    // in the namespace of person, we could abstract this function a little more!
    auto salary_burden(person const& x, person const& y) -> decltype(get_salary(x) + get_salary(y))
    {
        return get_salary(x) + get_salary(y);
    } 
}

// indeed in c++17 we could also abstract this concept completely...
template<class...Things>
auto salary_burden(Things&&...things)
{
    // here whatever namespace Things is in, this namespace will be
    // searched for a function called get_salary(Thing[&&|const&|&])
    return (get_salary(things) +  ...);
}

namespace non_humans 
{
    struct robot{};
    // note that a robot does not have a get_salary() member
    auto get_salary(robot const&) -> double { return 5; }
}

int main()
{
    auto alice = humans::person("alice", "the programmer", 20000);
    auto bob = humans::person("bob", "the builder", 10000);
    auto robby1 = non_humans::robot();
    auto robby2 = non_humans::robot();
    auto robby3 = non_humans::robot();

    // calls salary_burden(person const& x, person const& y)
    std::cout << salary_burden(alice, bob) << '\n';

    // calls auto salary_burden(Things&&...things)
    std::cout << salary_burden(alice, bob, robby1, robby2, robby3) << '\n';
}
#包括
#包括
命名空间人
{
班主任
{
私人:
//当然,永远不要在头文件中使用namespace::thing编写。
//如果要使用类型,请在非常有限的范围内使用cpp文件
std::字符串fname,lname;
双薪;
公众:
person(std::string,std::string,double);//构造函数声明
//这个类既不需要也不需要析构函数。
//如果定义析构函数,还必须定义复制和赋值
//运算符。请参见第5、3或无规则。
//定义查看薪资的方式
double get_salary()常量{return salary;}
//没有一个人加一个人这样的事情。
//避免无意义的数学抽象
//双操作员+(人);
};
//我们还提供了一个免费函数来获取工资,因为它在ADL中很有用
自动获取薪资(人员常量和薪资)->decltype(p.获取薪资())
{
返回p.get_salary();
}
//我们现在不需要成为朋友
//有办法得到薪水。因为有一个免费的功能可用
//在person的名称空间中,我们可以进一步抽象这个函数!
自动薪资负担(人员常量和x、人员常量和y)->decltype(获取薪资(x)+获取薪资(y))
{
返回获取工资(x)+获取工资(y);
} 
}
//实际上,在c++17中,我们也可以完全抽象这个概念。。。
模板
自动工资负担(事情和…事情)
{
//在这里,不管名称空间是什么,这个名称空间都是
//搜索名为get|u salary(Thing[&&&| const&&&&]的函数)
回报(拿薪水(东西)+…);
}
名称空间非人类
{
结构机器人{};
//请注意,robot没有get_salary()成员
自动获取工资(robot const&->double{return 5;}
}
int main()
{
自动爱丽丝=人类::人(“爱丽丝”,“程序员”,20000);
自动鲍勃=人类::人(“鲍勃”,“建设者”,10000);
auto robby1=非人类::机器人();
auto robby2=非人类::机器人();
auto robby3=非人类::机器人();
//呼叫薪资负担(人员常量和x、人员常量和y)

std::cout一些您可能会感兴趣的注释:

#include <string>
#include <iostream>

namespace humans
{
    class person
    {
    private:
        // certainly never write using namespace::thing in header files.
        // if you are going to be using a type, do it in a very confined scope, in a cpp file
        std::string fname, lname;
        double salary;

    public:
        person(std::string, std::string, double); // ctor declaration

        // you neither need or want a destructor for this class.
        // if you define a destructor, you must also define copy & assignment
        // operators. See rule of 5, 3 or none.

        // define a way to see the salary
        double get_salary() const { return salary; }

        // there is no such thing as a person plus a person.
        // avoid nonsensical mathematical abstractions
        // double operator+(person);
    };

    // let's also provide a free function to get_salary, because it can be useful in ADL
    auto get_salary(person const & p) -> decltype(p.get_salary())
    {
        return p.get_salary();
    }


    // salary_burden does not need to be a friend now that we
    // have a way to get the salary. Since there is a free function available
    // in the namespace of person, we could abstract this function a little more!
    auto salary_burden(person const& x, person const& y) -> decltype(get_salary(x) + get_salary(y))
    {
        return get_salary(x) + get_salary(y);
    } 
}

// indeed in c++17 we could also abstract this concept completely...
template<class...Things>
auto salary_burden(Things&&...things)
{
    // here whatever namespace Things is in, this namespace will be
    // searched for a function called get_salary(Thing[&&|const&|&])
    return (get_salary(things) +  ...);
}

namespace non_humans 
{
    struct robot{};
    // note that a robot does not have a get_salary() member
    auto get_salary(robot const&) -> double { return 5; }
}

int main()
{
    auto alice = humans::person("alice", "the programmer", 20000);
    auto bob = humans::person("bob", "the builder", 10000);
    auto robby1 = non_humans::robot();
    auto robby2 = non_humans::robot();
    auto robby3 = non_humans::robot();

    // calls salary_burden(person const& x, person const& y)
    std::cout << salary_burden(alice, bob) << '\n';

    // calls auto salary_burden(Things&&...things)
    std::cout << salary_burden(alice, bob, robby1, robby2, robby3) << '\n';
}
#包括
#包括
命名空间人
{
班主任
{
私人:
//当然,永远不要在头文件中使用namespace::thing编写。
//如果要使用类型,请在非常有限的范围内使用cpp文件
std::字符串fname,lname;
双薪;
公众:
person(std::string,std::string,double);//构造函数声明
//这个类既不需要也不需要析构函数。
//如果定义析构函数,还必须定义复制和赋值
//运算符。请参见第5、3或无规则。
//定义查看薪资的方式
double get_salary()常量{return salary;}
//没有一个人加一个人这样的事情。
//避免无意义的数学抽象
//双操作员+(人);
};
//我们还提供了一个免费函数来获取工资,因为它在ADL中很有用
自动获取薪资(人员常量和薪资)->decltype(p.获取薪资())
{
返回p.get_salary();
}
//我们现在不需要成为朋友
//有办法得到薪水。因为有一个免费的功能可用
//在person的名称空间中,我们可以进一步抽象这个函数!
自动薪资负担(人员常量和x、人员常量和y)->decltype(获取薪资(x)+获取薪资(y))
{
返回获取工资(x)+获取工资(y);
} 
}
//实际上,在c++17中,我们也可以完全抽象这个概念。。。
模板
自动工资负担(事情和…事情)
{
//在这里,不管名称空间是什么,这个名称空间都是
//搜索名为get|u salary(Thing[&&&| const&&&&]的函数)
回报(拿薪水(东西)+…);
}
名称空间非人类
{
结构机器人{};
//请注意,robot没有get_salary()成员
自动获取工资(robot const&->double{return 5;}
}
int main()
{
自动爱丽丝=人类::人(“爱丽丝”,“程序员”,20000);
自动鲍勃=人类::人(“鲍勃”,“建设者”,10000);
auto robby1=非人类::机器人();
auto robby2=非人类::机器人();
auto robby3=非人类::机器人();
//呼叫薪资负担(人员常量和x、人员常量和y)

std::cout编译器对此怎么说?无论如何,这是运算符重载的滥用,IMHO。这里有几个贡献者。
decltype
要求其操作数是完整的类型。更准确地说,因为
x+y
涉及函数调用,所以该函数调用不应该包含