반응형

종속적인 템플릿 이름은 template 키워드를 함께 사용해야 합니다.

#include <iostream>
#include <vector>
#include <list>
using namespace std;

class Test
{
public:
    template<typename T> static void f() {}
    template<typename T> class Complex {};
};

template<typename T> void foo(T a) // T: Test
{
    // OK
    Test::f<int>();

    // Error(임의 타입 T에서 < 연산자의 정의를 알 수 없음)
    //T::f<int>(); 

    // OK(임의 타입 T로 사용할 경우 ::template 키워드를 사용해야한다.)
    T::template f<int>();

    // OK
    Test::Complex<int> c1; 

    // Error(::Complex가 값인지 타입인지 알수 없음)
    //T::Complex<int> c2; 

    // Error(임의 타입 T에서 < 연산자 정의를 알 수 없음)
    //typename T::Complex<int> c3; 

    // OK(임의 타입 T로 사용할 경우 ::template 키워드를 사용해야한다.)
    typename T::template Complex<int> c4; 
}

int main()
{
    Test t;
    foo<Test>(t);
}
반응형

반응형

함수 템플릿을 구현하였을때  함수 내부에서 값의 타입이 필요할 경우

  • ::value_type 이용
  • 대신 auto 사용 가능
#include <iostream>
#include <vector>
#include <list>
using namespace std;

//컨테이너의 데이터 타입
template<typename T>
void print_first_element(T& v)
{
    // 1.값의 데이터 타입이 필요한 경우
    typename T::value_type n = v.front();
    
    // 2.값의 데이터 타입 대신 auto사용 가능
    auto n = v.front();
    
    cout << n << endl;
}

int main()
{
    list<double> v = { 1,2,3 };
    print_first_element(v);
}

 

C++ 17에서 클래스 템플릿 타입 추론(Class Template Type Deduction)에서 value_type 사용 예

 

#include <iostream>
#include <vector>
#include <list>
using namespace std;

template<typename T> 
class Vector
{
    T* buff;
    int size;
public:
    Vector(int sz, T value) {}

    template<typename C> Vector(C c) {}
};

// C++ 17의 클래스 사용자 정의 타입 추론을 정의할때 아래와 같이 값의 타입이 필요한 경우 auto 사용이 불가
template<typename C>
Vector(C c)->Vector<typename C::value_type>;

int main()
{
    Vector v(10, 3);
    
    // Vector에 list Container 인자로 넣을 경우, Container 내부 값의 타입 추론이 필요하다.
    list s = { 1,2,3 };
    Vector v2(s); 
}
반응형

반응형

클래스 이름::xx 접근 가능한 요소들

  • 값: enum 상수, static 멤버 변수

  • 타입: typedef, using

템플릿 의존적으로 타입의 이름에 접근할때는 typename 키워드를 붙여야한다.

  • T::DWORD -> 컴파일러가 DWORD를 값으로 해석

  • typename T:DWORD -> 컴파일러가 DWORD를 타입으로 해석

템플릿이 아닌 경우에는 typename을 사용할 수 없다.

  • typename T::DWORD* p; // OK

  • typename Test::DWORD* p; // Error

#include <iostream>
using namespace std;

class Test
{
public:
    enum { value1 = 1 };
    static int value2;
    typedef int INT;
    using SHORT = short;
    class innerClass {};
    using DWORD = int;
};
int Test::value2;

template<typename T>
int foo(T t)
{
    // 타입으로 해석
    //typename T::DWORD* p;
    
    // 값으로 해석
    //T::DWORD* p;

    return 0;
}

int main()
{
    Test t;
    foo(t);
}

 

 

반응형

반응형

클래스 템플릿안에 friend 함수를 선언하는 방법

  • friend 함수 선언시에 함수 자체를 템플릿 모양으로 선언

  • friend 관계: N:N

#include <iostream>
using namespace std;

template<typename T>
class Point
{
    T x, y;
public:
    Point(T a = { 0 }, T b = { 0 }) : x(a), y(b) {}
    template<typename U>
    friend ostream& operator<<(ostream& os, const Point<U>& p);
};

template<typename T>
ostream& operator<<(ostream& os, const Point<T>& p)
{
    return os << p.x << ", " << p.y;
}


int main()
{
    Point<int> p(1, 2);
    cout << p << endl;

    Point<double> p2(1.2, 2.3);
    cout << p2 << endl;
}

 

  • friend 함수를 일반 함수로 구현하고 구현부를 클래스 템플릿 내부에 포함

  • friend 관계: 1:1

#include <iostream>
using namespace std;

template<typename T>
class Point
{
    T x, y;
public:
    Point(T a = { 0 }, T b = { 0 }) : x(a), y(b) {}
    friend ostream& operator<<(ostream& os, const Point<T>& p)
    {
        return os << p.x << ", " << p.y;
    }
};


int main()
{
    Point<int> p(1, 2);
    cout << p << endl;

    Point<double> p2(1.2, 2.3);
    cout << p2 << endl;
}
반응형

반응형

일반화된 복사 생성자

  • 클래스 템플릿의 멤버 함수 템플릿으로 구현하는 복사 생성자.

  • U(int) T(double)로 복사(대입) 가능하다면 Complex<U> Complex<T>에 복사(대입) 가능해야 한다.

  • friend class로 선언되어야 한다.

template<typename T> class Complex
{
    T re, im;
public:
    Complex(T a = {}, T b = {}) : re(a), im(b) {}
    T getReal() const;
    static int cnt;
    template<typename U> T func(const U& c);

    // 일반화된 복사 생성자 선언
    template<typename U>
    Complex(const Complex<U>& c);

    template<typename> friend class Complex;
};

// 일반화된 복사 생성자 구현부
template<typename T> template<typename U>
Complex<T>::Complex(const Complex<U>& c)
    : re(c.re), im(c.im)
{

}

int main()
{
    Complex<int> c1(1, 1);
    Complex<int> c2 = c1;
    Complex<double> c3 = c1;
}
반응형

반응형

템플릿과 타입의 차이

  • Complex: 템플릿 틀 자체

  • Complex<T>: 실제 타입

  • 멤버 함수안에서는 

멤버 함수안에서는 Complex<T> 대신 Complex를 사용할 수 있다.

template<typename T> class Complex
{
    T re, im;
public:
    void foo(Complex c) // 멤버 함수에서는 OK(Complex<T> 동급으로 취급)
    {

    }
};

void foo(Complex c) // 일반 함수에서는 Error
{

}

void foo(Complex c)
{
    Complex c1; // Error
    Complex<int> c2; // OK
}

 

템플릿 관련 표기법

  • 디폴트 값 표기

    • int a = 0;

    • T a = T(); // C++ 98/03

    • T a = {};  // C++11

  • 멤버 함수를 외부에 표기

  • static memeber data 외부 표기

  • 클래스 템플릿의 멤버 함수 템플릿 표기

template<typename T> class Complex
{
    T re, im;
public:
	// 디폴트 값 표기
    Complex(T a = {}, T b = {}) : re(a), im(b) {}
    T getReal() const;
    static int cnt;

    template<typename U> T func(const U& c);
};

// 클래스 템플릿의 멤버 함수 템플릿 구현
template<typename T> template<typename U>
T Complex<T>::func(const U& c)
{

}

// static 멤버 데이터 외부 구현
template<typename T>
int Complex<T>::cnt = 0;

// 멤버 함수 외부 구현
template<typename T> 
T Complex<T>::getReal() const
{
    return re;
}

int main()
{
    Complex<int> c2;
}
반응형

반응형

IDFA란 무엇인가?

각 iOS 기기에서 타겟 광고를 게재하거나 앱 속성을 추척하기 위한 고유한 ID 값입니다.

iOS6부터 소개되어 iOS13까지 아래처럼 쉽게 사용할 수 있었습니다.

import AdSupport

var idfa: UUID {
	return AsIdentifierManager.shared().advertisingIdentifier
}

 

iOS14

iOS14를 대상으로 하는 앱들은 IDFA 접근을 위해서 AppTrackingTransparency, AdSupport 2개의 프레임워크 사용이 필요합니다.

 

AppTrackingTranparency 통해 개발자가 IDFA를 ASIdentifierManager에서 직접 조회하는 대신에 사용자에게 IDFA 읽기 권한을 요청할 수 있습니다.

 

※ 권한 요청은 앱 설치 당 오직 1회 요청만 가능

 

Info.plist 업데이트

사용자에게 알리기 위한 메시지를 추가 작업이 필요합니다.

어떤 사유로 앱이 사용자 또는 디바이스 추적을 위한 데이터를 사용하기 위해서 권한이 필요한지에 대한 설명입니다.

해당 메시지는 앱속의 Info.plist에 추가 해야합니다.

//Privacy - Tracking Usage Description
<key>NSUserTrackingUsageDescription</key>
<string>앱이 타겟광고게재 추적 목적으로 IDFA에 접근하려고 합니다.</string>

Info.plist에 메시지를 추가 했으면 계정에 권한 요청을 위해서 로컬 코드를 업데이트 해야합니다.

 

권한 요청

  • Status: Authorized
    • IDFA를 ASIdentifierManager에서 조회
  • Status: Denied
    • 사용자 설정 페이지로 이동
  • Status: Not Determined
    • 사용자에게 권한을 요청하고 다이얼로그를 표시
import AdSupport
import AppTrackingTransparency
func requestPermission() {
    ATTrackingManager.requestTrackingAuthorization { status in
        switch status {
        case .authorized:
            // Tracking authorization dialog was shown 
            // and we are authorized
            print("Authorized")
        
            // Now that we are authorized we can get the IDFA
	    print(ASIdentifierManager.shared().advertisingIdentifier)
        case .denied:
           // Tracking authorization dialog was 
           // shown and permission is denied
             print("Denied")
        case .notDetermined:
                // Tracking authorization dialog has not been shown
                print("Not Determined")
        case .restricted:
                print("Restricted")
        @unknown default:
                print("Unknown")
        }
    }
}

 

  • 어떻게 권한 요청을 하는지 애플 다이얼로그 예제입니다.
  • 만약 사용자가 권한을 허용하지 않는다면 UUID값은 모두 0으로 표기되어 반환됩니다.
  • 파란색 박스가 개발자가 앱속 Info.plist에 추가 작업한 메시지가 표시되는 영역입니다.

 

Origin Link : https://medium.com/@nish.bhasin/how-to-get-idfa-in-ios14-54f7ea02aa42

 

How to get IDFA in iOS14

What is IDFA?

medium.com

 

반응형

반응형

Flutter 전체 구성을 진단하는 명령어인 flutter doctor 실행 시 아래와 같이

Android license status unknown 에러가 발생 한다면

아래의 명령어를 실행하여 각각의 라이선스에 대하여 Accepted하면 해결 할 수 있다.

flutter doctor --android-licenses

 

반응형

+ Recent posts