読者です 読者をやめる 読者になる 読者になる

テンプレート引数の強制

C++

melt日記 - template での参照型と値型



型Tが参照型か判断するメタ関数を作成し

template <class T>
struct is_reference {
    static const bool value = false;
};

template <class T>
struct is_reference<T&> {
    static const bool value = true;
};


以下のような処理を書くと、参照型の引数を渡しても値型として処理されてしまう

template <class T>
void func(T value)
{
    printf("%s\n", is_reference<T>::value ? "参照型" : "値型");
}

int main()
{
    int value = 3;
    func(value);

    int& ref_value = value;
    func(ref_value);

    return 0;
}
値型
値型


テンプレート引数を明示化すると、参照型は参照型として正しく処理される

int main()
{
    int value = 3;
    func<int>(value);

    int& ref_value = value;
    func<int&>(ref_value);

    return 0;
}
値型
参照型


こういった処理の場合、テンプレート引数の指定を強制することが以下の方法でできる

template <class T>
struct identity {
    typedef T type;
}
template <class T>
void func(typename identity<T>::type value)
{
    printf("%s\n", is_reference<T>::value ? "参照型" : "値型");
}

int main()
{
    int value = 3;
    func<int>(value);

    int& ref_value = value;
    func<int&>(ref_value);

    func(value); // エラー!型Tが指定されていません

    return 0;
}
値型
参照型


なお、参照だけではなくconst修飾にも同じ問題がある

template <class T>
struct is_const {
    static const bool value = false;
};

template <class T>
struct is_const<T const> {
    static const bool value = true;
};
template <class T>
void func(T value)
{
    printf("%s\n", is_const<T>::value ? "const" : "not const");
}

int main()
{
    int const value = 3;
    func(value);

    func<int const>(value);
    return 0;
}
not const
const

これも同様にidentityを使用してテンプレート引数を強制することで解決する




【参考サイト】

低学歴無能俸給生活者の日記>< - implicit_castの実装