C++ Dilinde Literal Operator Fonksiyonları ve Kullanımı Senaryoları
- Yusuf Hançar
- Jul 28, 2024
- 6 min read
Updated: Jul 31, 2024
C++ dilinde literal operator fonksiyonları, sabit değerlerin (literal) işlenmesini ve kullanıcı tanımlı sabitlerin oluşturulmasını sağlamaktadır. C dili genellikle "constant" terimini kullanırken, C++ "literal" terimini tercih eder.
Literaller iki ana kategoride incelenir: cooked (işlenmiş) ve raw (işlenmemiş)
Cooked literaller, derleyici tarafından işlenmiş ve belirli bir türde fonksiyona geçirilmiş değerlerdir. Örneğin; bir tam sayı ya da gerçek sayı kullanarak ona son ek ekleyeceksek derleyici 123_k şeklindeki ifadedeki 123 ifadesini fonksiyona tam sayı türünden değer olarak geçilir ve buna cooked denir.
int main ()
{
"smartcode"s // bu kütüphane tarafından yazılan fonksiyona çağrıdır
"smartcode"_s // biz yazarsak literal operator fonksiyonu _ ile başlamalıdır.
}
#include <iostream>
#include <cmath>
using namespace std;
int operator""_sr(unsigned long long val)
{
cout << "operator""_sr : " << val << endl;
return static_cast<int>(std::sqrt(val));
}
int main()
{
auto val = 36_sr;
cout << val << endl;
}
******************************
CEVAP :
operator_sr : 36
6
******************************
AÇIKLAMA : cooked
******************************
#include <iostream>
using namespace std;
int operator""_bin(const char* str)
{
int ret{};
while (*str)
{
if (!(*str == '0' || *str == '1'))
{
throw std::runtime_error{ "bad binary constant!" };
}
ret = ret * 2 + (*str - '0');
++str;
}
return ret;
}
int main()
{
auto val = 101101011_bin;
cout << val << endl;
}
******************************
CEVAP : 363
******************************
AÇIKLAMA : raw(uncooked)
******************************
#include <iostream>
#include <stdexcept>
#include <algorithm>
#include <numeric>
#include <string>
using namespace std;
int operator"" _bin(const char* str)
{
std::string stmp{str};
// tüm karakterlerin '0' veya '1' olduğunu kontrol için std::all_of
if (!std::all_of(stmp.begin(), stmp.end(),
[](char chr) { return chr == '0' || chr == '1'; }))
{
throw std::runtime_error("bad binary constant!");
}
return std::accumulate(stmp.begin(), stmp.end(), 0, [](int acc, char chr) {
return acc * 2 + (chr - '0');
});
}
int main()
{
auto val = 101101011_bin;
cout << val << "\n";
}
******************************
CEVAP : 363
******************************
AÇIKLAMA : raw(uncooked)
******************************
constexpr olarak kullanılabilir...
constexpr int operator""_bin(const char* str)
{
// syntax error. constexpr fonksiyon için static yerel değişken tanımlanamaz.
static int ret{};
while (*str)
{
if (!(*str == '0' || *str == '1'))
{
throw std::runtime_error{ "bad binary constant!" };
}
ret = ret * 2 + (*str - '0');
++str;
}
return ret;
}
int main()
{
auto val = 101101011_bin;
cout << val << endl;
}
******************************
CEVAP : syntax error
******************************
constexpr int operator""_bin(const char* str)
{
int ret{};
while (*str)
{
if ((!(*str == '0') || (*str == '1')))
{
throw std::runtime_error{ "bad binary constant!" };
}
ret = ret * 2 + (*str - '0');
++str;
}
return ret;
}
int main()
{
constexpr auto val = 101101011_bin;
cout << val << endl;
}
******************************
CEVAP : syntax error
******************************
AÇIKLAMA : constexpr fonksiyonlarda throw ifadesi kullanılamaz çünkü constexpr fonksiyonlar derleme zamanında sabit bir ifade olarak değerlendirilmelidir. Hata kontrolünü derleme zamanında gerçekleştirmek için şablonlar veya yardımcı constexpr fonksiyonlar kullanmaktır.
******************************
int main()
{
"smartcode"s;
}
******************************
CEVAP : syntax error
******************************
int main()
{
using namespace std::literals;
"smartcode"s;
}
******************************
CEVAP : legal
******************************
#include <iostream>
int operator""_ch(char val)
{
return static_cast<int>(val);
}
int main()
{
std::cout << 'A' << "\n";
std::cout << 'A'_ch << "\n";
}
*****************************
AÇIKLAMA :
*****************************
CEVAP :
A
65
*****************************
#include <iostream>
void operator""_ch(const char* val)
{
std::cout << val << "\n";
}
int main()
{
34.56_ch;
}
*****************************
AÇIKLAMA :
*****************************
CEVAP : 34.56
*****************************
#include <iostream>
#include <vector>
using namespace std;
vector<char> operator""_v(const char* ptr, size_t cnt)
{
vector<char> ret;
while (*ptr)
{
ret.push_back(*ptr++);
}
return ret;
}
int main()
{
auto vec = "smartcode"_v;
cout << "vec.size() : " << vec.size() << endl;
}
*****************************
AÇIKLAMA : string literali aldık char vector haline getirdik.
*****************************
CEVAP : vec.size() : 9
*****************************
class Data {};
int main()
{
Data d;
double dval = 56.88;
d = 4.44_m; // bu geçerli olsun.
d = 4.45; // bu şekilde double değer atamak sentaks hatası olsun
}
#include <iostream>
class Data {
public:
struct PreventUsage{};
// Constructor tanımı
Data(PreventUsage, double dval) : m_val(dval) {}
private:
double m_val;
};
Data operator""_mt(long double val)
{
// long double daha büyük ve uyarı verir cast yapmazsak(narrowing conversion)
return Data{ Data::PreventUsage{}, static_cast<double>(val) };
}
int main()
{
Data d = 4.44_mt; // Data d = 4.44; error
return 0;
}
raw string literal
ayrı bir tür değildir ve yazım biçimi oluşturma yöntemidir.
C++11 ile standartlara eklenmiştir.
R"()" formatındadır.
#include <iostream>
#include <type_traits>
using namespace std;
int main()
{
cout << sizeof(R"(codes)") << "\n";
cout << sizeof("codes") << "\n";
cout << boolalpha << is_same_v<decltype("cpp"), const char(&)[4]> << "\n";
cout << boolalpha << is_same_v<decltype(R"(cpp)"), const char(&)[4]> << "\n";
}
*****************************
CEVAP :
6
6
true
true
*****************************
#include <iostream>
#include <type_traits>
using namespace std;
int main()
{
const char* p = R"(smart \code \ cpp
developed
cpp17)";
puts(p);
}
*****************************
CEVAP :
smart \code \ cpp
developed
cpp17
*****************************
#include <iostream>
#include <type_traits>
using namespace std;
int main()
{
auto p = R"loc("(smartcode"))loc";
puts(p);
}
*****************************
AÇIKLAMA : loc burada bir ham dizgi literalinde delimiter olarak kullanılır. raw string literals, özel karakterleri escape sequence olmadan olduğu gibi yazmanızı sağlar ve özellikle çok satırlı dizgiler veya içinde tırnak işaretleri gibi özel karakterler içeren dizgiler için faydalıdır. loc gibi bir sınırlayıcı kullanarak, ham dizgi literalinin başlangıcı ve sonu belirlenebilir.
*****************************
CEVAP : "(smartcode")
*****************************
manipulator
quoted(...)
geri dönüş değeri string değil tamamen derleyiciye bağlıdır.
default argument alır.
<iomanip> başlık dosyasında bulunur ve giriş/çıkış işlemlerinde dizgileri (string) yönetmek için kullanılır. Özellikle, boşluklar, özel karakterler veya içine gömülü tırnak işaretleri içeren dizgilerle uğraşırken faydalıdır.
#include <iomanip>
#include <iostream>
using namespace std;
int main()
{
string str = "smart, \"code\"!";
std::cout << str << "\n";
}
*****************************
CEVAP : smart, "code"!
*****************************
#include <iomanip>
#include <iostream>
using namespace std;
int main()
{
string str = "smart, \"code\"!";
std::cout << quoted(str) << "\n";
}
*****************************
CEVAP : "smart, \"code\"!"
*****************************
#include <iomanip>
#include <iostream>
#include <sstream>
int main()
{
std::istringstream iss("\"smart, \\\"code\\\"!\"");
std::string str;
iss >> quoted(str);
std::cout << str << "\n";
}
*****************************
CEVAP : smart, "code"!
*****************************
C++ dilinde yaygın olarak kullanılan diğer manipülatörler :
std::endl, std::setw, std::setprecision, std::fixed, std::scientific, std::hex, std::dec, std::oct, std::showbase, std::noshowbase, std::uppercase, std::nouppercase, std::left, std::right, std::internal, std::setfill.
std::cout << std::setw(5) << 15 << "\n";
*****************************
AÇIKLAMA : Bir sonraki giriş/çıkış işlemi için alan genişliğini ayarlar.
*****************************
std::cout << std::setprecision(3) << 3.14159 << "\n"; // 3.14
*****************************
AÇIKLAMA :Ondalık nokta hassasiyetini ayarlar
*****************************
std::cout << std::fixed << 3.14159 << "\n"; // 3.141590
std::cout << std::scientific << 3.14159 << "\n"; // 3.141590e+00
*****************************
AÇIKLAMA : Ondalık sayıları sabit noktada veya bilimsel gösterimde formatlar.
*****************************
int cnt = 255;
std::cout << std::hex << cnt << "\n"; // ff
std::cout << std::dec << cnt << "\n"; // 255
std::cout << std::oct << cnt << "\n"; // 377
*****************************
AÇIKLAMA : onaltılık (hexadecimal), ondalık (decimal) veya sekizlik (octal) tabanda yazar
*****************************
std::cout << std::showbase << std::hex << 255 << "\n"; // 0xff
std::cout << std::noshowbase << std::hex << 255 << "\n"; // ff
*****************************
AÇIKLAMA : taban ön eklerini gösterir veya gizler (örneğin, 0x for hex, 0 for oct).
*****************************
std::cout << std::uppercase << std::hex << 255 << "\n"; // FF
std::cout << std::nouppercase << std::hex << 255 << "\n"; // ff
*****************************
AÇIKLAMA : Hexadecimal ve bilimsel gösterimlerde harfleri büyük veya küçük yazar
*****************************
std::cout << std::setw(10) << std::left << 123 << "\n"; // "123 "
std::cout << std::setw(10) << std::right << 123 << "\n"; // " 123"
std::cout << std::setw(10) << std::internal << -123 << "\n"; // "- 123"
*****************************
AÇIKLAMA : Metni sola, sağa veya içe hizalar
*****************************
std::cout << std::setw(10) << std::setfill('*') << 123 << "\n"; // "*******123"
*****************************
AÇIKLAMA : Alanları doldurmak için kullanılan karakteri belirler
*****************************
#include <iomanip>
#include <sstream>
#include <iostream>
int main ()
{
std::ostringstream oss;
oss << "\"smartcode\"";
std::cout << oss.str() << "\n";
}
*****************************
AÇIKLAMA :
*****************************
CEVAP : "smartcode"
*****************************
#include <iomanip>
#include <sstream>
#include <iostream>
int main ()
{
std::ostringstream oss;
oss << std::quoted("\"smartcode\"");
std::cout << oss.str() << "\n";
}
*****************************
AÇIKLAMA : çift tırnaklar yakalandı.
*****************************
CEVAP : "\"smartcode\""
*****************************
#include <iomanip>
#include <sstream>
#include <iostream>
int main ()
{
std::ostringstream oss;
// default argument yerine '*' eklendi
oss << std::quoted("smartcode", '*');
std::cout << oss.str() << "\n";
}
*****************************
AÇIKLAMA : çift tırnaklar yakalandı.
*****************************
CEVAP : *smartcode*
*****************************
#include <iomanip>
#include <sstream>
#include <iostream>
int main ()
{
std::stringstream ss;
ss << std::quoted("\"yusuf\"");
std::string name;
ss >> std::quoted(name);
std::cout << name << "\n";
}
*****************************
AÇIKLAMA :
*****************************
CEVAP : "yusuf"
*****************************
Comments