C++ 11 덕분에 이제는 매크로, 사용자 정의 리터럴, 람다 등을 결합하여 '구문 설탕'에 가장 가까이있는 것을 만들 수 있습니다. 예를 들어새 삽입 연산자 정의
if (A contains B)
물론 쉽습니다.
cout <<("hello"_s contains "ello"_s)<<endl;
식은 인수로서 좌측과 우측을 얻어 맞춤 구조체이다 포함 BOOL로 변환한다. 구조체는 operator +를 오버로드하여 사용자 정의 문자열 리터럴을 먼저 가져 와서 자체를 반환 한 다음 구조체 자체에 대한 연산자 +를 오버로드합니다.
struct contains_struct {
string lhs;
string rhs;
void set_lhs(string lhs) { this->lhs = lhs; }
void set_rhs(string rhs) { this->rhs = rhs; }
operator bool() const {
return string::npos != lhs.find(rhs);
}
} contains_obj;
contains_struct& operator+(const string& lhs, const contains_struct& rhs) {
contains_obj.set_lhs(lhs);
return contains_obj;
}
contains_struct& operator+(const contains_struct& lhs, const string& rhs) {
contains_obj.set_rhs(rhs);
return contains_obj;
}
#define contains +contains_obj+
이제 나는 더 가고 싶다고 결정했습니다. 어떤 약
(x in a) perform cube
그것은 목록의 이해가 아니지만 그것은 꽤 좋은 예입니다. 처음에는 잘 정의 된 연산자 우선 순위에 대해 물어보기 위해 stackoverflow에 가야 겠지만 올바른 생각을 가진 사람이 내 코드를 사용하지 않으므로 괄호 안에 넣는 것이 간단합니다. 대신, 나는 다른 예제를 확장하고 '포함'과 같이 사용자 지정 구조체로 'in'및 'perform'을 포함합니다.
x가 임의의 숫자 인덱스가 될 수 있도록 템플릿을 추가하고 템플릿을 만들 수 있지만 간단히하기 위해 x는 정수로, a는 int 벡터로 남겨 둡니다. 이제까지는 로컬 변수 x를 인수로 사용하지 않고 operator string() 함수에서 로컬 변수를 사용합니다. Overloading assignment operator for type deduction
내가 그것을 반환에 대해 하나의 실용화를 실현 : 일을 단순화하기 위해
, 나는 또 다른 질문에 이렇게
operator string() const {
string s = "";
for (int x : lhs.rhs)
s += to_string(rhs(x)) + string("\n");
return s;
}
같은 문자열
감사 식의 결과를 저장
struct result_struct {
vector<int> results;
result_struct(vector<int> results) { this->results = results; }
};
...
operator result_struct() const {
vector<int> tmp;
for (int x : lhs.rhs)
tmp.push_back(rhs(x));
return result_struct(tmp);
}
...
result_struct result_2 = (x in a) perform cube;
for (int x : result_2.results)
cout <<x<<endl;
: 과제는 다음과 같다 milleniumbug's answer에 617,451,515,
덕분에, 내가 할 수있는 :
struct for_obj
{
int _lhs;
std::vector<int> _rhs;
for_obj(int lhs, std::vector<int> rhs)
: _lhs(lhs), _rhs(rhs) { }
};
INFIX_OPERATOR(for_obj, in_op, int, std::vector<int>)
{
return for_obj(lhs(), rhs());
}
#define in + in_op() +
INFIX_OPERATOR(int, perform_op, for_obj, std::function<int(int)>)
{
for (int i = 0; i < lhs()._rhs.size(); i++)
rhs()(lhs()._rhs[i]);
return 0;
}
#define perform + perform_op() +
두 가지주의 사항이 있습니다. 먼저 int를 반환하여 더미 변수에 할당하여 실행할 수 있도록합니다. 나는 항상 전에했던 result_struct 일을 할 수도 있고 std :: function 객체를 반환하여 그 자체로 호출 할 수도 있지만 나 자신을 반복 할 것입니다. 다른주의 사항은 매크로에 너무 많은 const가 있기 때문에 lhs를 수정할 수 없다는 것입니다 (반복자를 지정할 수는 없습니다).
모든 사항은 다음과 같이 예상됩니다.
int x = 0;
std::vector<int> nums = { 1, 2, 3 };
auto cube = [] (int x)
{
std::cout << x * x * x << std::endl;
return x * x * x;
};
int i = (x in nums) perform cube;
새로운
class PerformObj {
int counter;
public:
PerformObj() : counter(0) { }
~PerformObj() { }
InObj lhs;
std::function<int(int)> rhs;
operator int() const {
return rhs(lhs.rhs[counter]);
}
} performobj;
#define perform + performobj +
PerformObj& operator+(const InObj& lhs, PerformObj& rhs) {
rhs.lhs = lhs;
return rhs;
}
PerformObj& operator+(PerformObj& lhs, const std::function<int(int)>& rhs) {
lhs.rhs = rhs;
return lhs;
}
int main()
{
std::vector<int> nums = {1,2,3};
int x = 0;
auto cube = [] (int n) {
return n * n * n;
};
std::cout << x in nums perform cube << std::endl;
}
explicit operator std::vector<int>() const {
std::vector<int> temp;
for (int i = 0; i < lhs.rhs.size(); i++) {
temp.push_back(rhs(lhs.rhs[i]));
}
return temp;
}
int y = 0;
std::cout << y in static_cast<std::vector<int>>(x in nums perform cube) perform std::function<int(int)>([] (int i) -> int {
return i;
}) << std::endl;
내가 그것을 그렇게 그 대신 중위 연산자, 후위 운영자가 확인해야 버전, "String literal"s.contains "Other string literal"s
같은, 또는 기능 스타일을, "String literal"s.contains("Other string literal"s)
?
확장 성을 높이기 위해 코드를 개선하는 방법은 무엇입니까? 지금 당장은 매우 오염되었습니다. 이 작업을 수행하는 더/더 일반화 된/덜 clunky 한 방법이 있습니까? 예를 들어, 표현식을 일반화하여 정의 문이 필요 없거나 코드를 재사용 할 수 있습니다.
이 난처에 대한 좋은 기술이지만, definitly해야 그렇지 않으면 피하십시오. C++을 아는 사람이 코드를 읽을 수 없도록 만듭니다. –
표현 템플릿을 재발 명하는 것 같습니다 ... 용어를 찾아 보면 충분히 찾을 수 있습니다. 그러나 언어에 새로운 중절 삽입 연산자를 도입하는 것은 나쁜 생각입니다. 함수 호출 표기법을 고수하거나 인기를 잃습니다. – Potatoswatter
흥미롭고 깔끔하기 때문에 나는 이것을 upvoting하고있다. 그러나 나는 실제 코드에서 실제 사용을 위해 그것을지지하지 않는다. –