반응형

modernize-pass-by-value

With move semantics added to the language and the standard library updated with move constructors added for many types it is now interesting to take an argument directly by value, instead of by const-reference, and then copy. This check allows the compiler to take care of choosing the best way to construct the copy.

언어에 이동 의미론(move semantics)이 추가되고
많은 타입에 대한 이동 생성자(move constructors)가 추가된 표준 라이브러리가 업데이트되면서
이제는 const-reference 대신, 직접 값으로 인자를 받고 복사하는 것이 흥미롭다.
이 검사를 통해 컴파일러는 복사본을 생성하는 가장 좋은 방법을 선택할 수 있습니다.

 

The transformation is usually beneficial when the calling code passes an rvalue and assumes the move construction is a cheap operation. This short example illustrates how the construction of the value happens:

이 변환은 보통, 호출 코드가
rvalue을 전달(passes an rvalue)하고 이동 생성(move construction)이 저렴한 작업이라고 추정할 때 유용합니다.
이 짧은 예는 값의 생성이 어떻게 이루어지는지 보여줍니다.
=> 해설 : 매개변수 s가 pass by value 지만, lvalue와 rvalue에 따라 copy, move 를 선택한다

void foo(std::string s);
std::string get_str();

void f(const std::string &str) {
  foo(str);       // lvalue  -> copy construction
  foo(get_str()); // prvalue -> move construction
}

 

Note
Currently, only constructors are transformed to make use of pass-by-value. Contributions that handle other situations are welcome!

주의
현재 생성자만 pass-by-value를 사용하도록 변환됩니다. 다른 상황을 처리하는 기여도 환영합니다!

 

 

Pass-by-value in constructors

Replaces the uses of const-references constructor parameters that are copied into class fields. The parameter is then moved with std::move().
Since std::move() is a library function declared in <utility> it may be necessary to add this include. The check will add the include directive when necessary.

클래스 필드로 복사되는 const-reference 생성자 매개변수의 사용을 교체합니다.
이 매개변수는 std::move를 통해 이동됩니다.
std::move()는 <utility>에 선언된 라이브러리 함수이므로 이 include문의 추가가 필요할 수도 있습니다.
이 검사는 필요한 경우 포함문을 추가합니다.

 #include <string>

 class Foo {
 public:
-  Foo(const std::string &Copied, const std::string &ReadOnly)
-    : Copied(Copied), ReadOnly(ReadOnly)
+  Foo(std::string Copied, const std::string &ReadOnly)
+    : Copied(std::move(Copied)), ReadOnly(ReadOnly)
   {}

 private:
   std::string Copied;
   const std::string &ReadOnly;
 };

 std::string get_cwd();

 void f(const std::string &Path) {
   // The parameter corresponding to 'get_cwd()' is move-constructed. By
   // using pass-by-value in the Foo constructor we managed to avoid a
   // copy-construction.
   Foo foo(get_cwd(), Path);
 }
If the parameter is used more than once no transformation is performed since moved objects have an undefined state. It means the following code will be left untouched:

매개변수를 한번 이상 사용하지 않으면 변환이 수행되지 않는다,
왜냐하면 이동된 객체의 상태가 정의되지 않았기 때문이다.
다음 코드가 변경되지 않는 상태로 유지됨을 의미한다.

 

#include <string>

void pass(const std::string &S);

struct Foo {
  Foo(const std::string &S) : Str(S) {
    pass(S);
  }

  std::string Str;
};

 

Known limitations

A situation where the generated code can be wrong is when the object referenced is modified before the assignment in the init-list through a “hidden” reference.

생성된 코드가 틀릴 수 있는 상황은
init-list로 초기화 되기 전에 숨겨진 참조에 의해 참조된 객체가 변경되는 경우이다.

 

Example:

 std::string s("foo");

 struct Base {
   Base() {
     s = "bar";
   }
 };

 struct Derived : Base {
-  Derived(const std::string &S) : Field(S)
+  Derived(std::string S) : Field(std::move(S))
   { }

   std::string Field;
 };

 void f() {
-  Derived d(s); // d.Field holds "bar"
+  Derived d(s); // d.Field holds "foo"
 }

 

Not about delayed template parsing

When delayed template parsing is enabled, constructors part of templated contexts; templated constructors, constructors in class templates, constructors of inner classes of template classes, etc., are not transformed. Delayed template parsing is enabled by default on Windows as a Microsoft extension: Clang Compiler User’s Manual - Microsoft extensions.

Delayed template parsing can be enabled using the -fdelayed-template-parsing flag and disabled using -fno-delayed-template-parsing.

Example:

  template <typename T> class C {
    std::string S;

  public:
=  // using -fdelayed-template-parsing (default on Windows)
=  C(const std::string &S) : S(S) {}

+  // using -fno-delayed-template-parsing (default on non-Windows systems)
+  C(std::string S) : S(std::move(S)) {}
  };

See also

For more information about the pass-by-value idiom, read: Want Speed? Pass by Value.

Options

IncludeStyle

A string specifying which include-style is used, llvm or google. Default is llvm.

ValuesOnly

When true, the check only warns about copied parameters that are already passed by value. Default is false.


출처

함께 보면 좋은 글

반응형
반응형

아래 처럼 조건문에서 입력과 조건체크를 함께 진행하는 경우 유용할 수 있습니다.

 if (numeric_read(str, &err), !err)

numeric_read함수는 호출만 되고, !err 조건만 판단하게 됩니다.

 

 

콤마 연산자에 대한 자세한 설명은 아래 링크들을 참고해주세요

https://dad-rock.tistory.com/117

https://www.inflearn.com/questions/137837

https://stackoverflow.com/questions/16475032/comma-operator-in-if-condition

반응형
반응형

Build and Use Go Packages as C Libraries

GO의 공식기능인 CGO를 통해 C라이브러리를 참조하는 GO패키지를 만들 수 있습니다.

놀랍게도 그뿐아니라, 반대로 C에서 GO를 참조할 수 있도록 GO패키지에서 C라이브러리를 만들 수도 있습니다. 

 

How to

Build Go package as C shared library (or shared object)

모든 GO main 패키지는 C 공유 라이브러리로 빌드될 수 있어요.

$ go build -go build -buildmode c-shared -o <c-lib>.so <go-package>

 

위 명령을 실행하면 대상이된 Go main 패키지의 모든 종속성을 C공유라이브러리 하나로 빌드합니다.

이 C공유 라이브러리를 참조할 수 있는 모든 어플리케이션에 배포,설치, 링크할 수도 있습니다.

 

주의 : C공유라이브러리의 output 이름은 lib*.so 로 표준형식으로 지정해야합니다.

 

Generate C header and export Go functions as C functions

Go main package를 C shared library로 빌드한다고 해서 자동으로 C헤더를 생성하거나 Go함수를 C심볼로 노출하지 않습니다. 이건 개발자가 명시적으로 어떤 Go 함수를 노출할지 지정해야합니다.

 

 

Go 함수를 C 심볼로 export 하기

  • export 할 Go 함수 위에 //export FuncName 으로 주석을 추가합니다.

  • 이 함수가 있는 Go 코드파일에 import "c" 를 넣어주세요

  • 이 함수는 main 패키지에 포함되어 있어야합니다.

  • 함수 signature 에 Go struct, interface, array나 가변인수가 포함될 수 없습니다.

 

package main  

import "C"

import (
    "math/rand"
    "time"
)

//export cgoCurrentMillis
func cgoCurrentMillis() C.long {
    return C.long(time.Now().Unix()) 
}

//export cgoSeed
func cgoSeed(m C.long) {
    rand.Seed(int64(m))
}

//export cgoRandom
func cgoRandom(m C.int) C.int {     
    return C.int(rand.Intn(int(m))) 
}

위 Go main 패키지를 빌드하면 C헤더파일 <output.h> 과 C공유객체 <output>.so가 생성됩니다.

 

 

// Other stuff.  

extern long int cgoCurrentMillis();  

extern void cgoSeed(long int p0);  

extern int cgoRandom(int p0);

cgoCurrentMilli, cgoSeed 및 cgoRandom 도 <output>.so 에 C 심볼로 노출됩니다. 

 

 

이제 모든 C어플리케이션에서 만들어진 C헤더를 include 하고 C공유라이브러를 link해서 export된 C심볼을 사용할 수 있습니다.

 

 

#include <stdio.h> 
#include <cgo-random.h>  

int main() {     
    cgoSeed(cgoCurrentMilli());     
    
    printf("Hello World from C!\n");     
    printf("cgoRandom() -> %d\n", cgoRandom(256));   
    return 0;
}

 

 

원문 : 

https://medium.com/swlh/build-and-use-go-packages-as-c-libraries-889eb0c19838

 

Build and Use Go Packages as C Libraries

CGO is an official builtin feature of Go, it enables the creation of Go packages that reference to C libraries. But it isn’t just that, it…

medium.com

 

 

반응형
반응형

 

#define _CRT_SECURE_NO_WARNINGS

#include <sstream>
#include <chrono>
#include <time.h>
#include <iomanip>
#include <iostream>

std::stringstream Timestamp()
{
    auto now = std::chrono::system_clock::now();
    std::time_t t = std::chrono::system_clock::to_time_t(now);
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();

    std::stringstream ss;
    ss << std::put_time(std::localtime(&t), "%F %T.") << std::setfill('0') << std::setw(3) << ms % 1000;
    return ss;
}

int main()
{
    std::cout << Timestamp().str() << std::endl;
    return 0;
}

 

출력 예시

2021-08-19 23:27:03.063

 

 

(milliseconds를 epoch 나머지로 직접 구하는 방법 말고는 없는걸까? 기본 제공되는 함수라던가)

 

반응형

+ Recent posts