对于以下代码:
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说cannot convert to incomplete class "person"
这是怎么回事?
注:包括ctor和dtor在内的方法的定义位于不同的翻译单元中。我想这不是这里错误的原因。
答案 0 :(得分:2)
问题在于,即使decltype
的操作数可能是不完整的类型,对于用来构成用作decltype
的prvalue的prvalue的子表达式也不相同。
decltype(x+y);
等效于
decltype(operator+(x, y));
但是person
在其自己的定义中不完整。您可以通过将operator+
定义为:
double operator+(person const&);
答案 1 :(得分:1)
您可能会发现有趣的一些笔记:
#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';
}