4

私はこのような名前の定数をいくつか持っています:

template<int n> class usart {
private:
    usart();
public:
    enum class tx {};
    enum class rx {};
    enum class ck {};
};

template<> class usart<1> {
public:
    enum class tx { A9  = gpio::A9,  C4 = gpio::C4 };
    enum class rx { A10 = gpio::A10, C5 = gpio::C5 };
    enum class ck { A8  = gpio::A8 };
};

// two more of these

ここで、gpioは単純な整数列挙型です。

別のファイルでクラスに型安全性を適用したいと思います。

class USART {
public:
    template<int N>
    USART(typename usart<N>::tx pin_tx, typename usart<N>::rx pin_rx) {
        //This signature enforces correct pins with types, doesn't it?
    }
};

ただし、これを使用すると

USART us = USART(usart<1>::tx::A9, usart<1>::rx::A10);

エラーが発生します

error: expected ')' before 'pin_tx'

この構文が違法なのはなぜですか? 編集typename

これで、クラスをインスタンス化しようとすると、次のエラーが発生します。

error: no matching function for call to 'USART::USART(usart<1>::tx, usart<1>::rx)'
note: template<int N> USART::USART(typename usart<N>::tx, typename usart<N>::rx)
note:   template argument deduction/substitution failed:
note:   couldn't deduce template parameter 'N'
4

1 に答える 1

15

関数の引数で使用されるテンプレートパラメータは、引数が依存型であるため、推論できません。

「でもそれはばかげている!」あなたは言うでしょう; 「Nが1であることは明らかです!なぜコンパイラはそれを推測するための賢さを持たないのですか?」

次のことを考慮してください。

template<> class usart<4321> {
public:
    typedef usart<1>::tx tx;
    typedef usart<1>::rx rx;
    typedef usart<1>::ck ck;
};

Nは1または4321である必要がありますか?結局のところ、usart<4321>::txusart<1>::tx同じタイプです。

コンパイラは、usartの1つのインスタンス化のみがメンバーとしてその正確な型を持っていることを確認せずに、Nがどうあるべきかを知ることはできませんtx。これには、インスタンス化が多すぎるか、ロジックが複雑すぎて、一般的なケースではインスタンス化が発生しないことを証明できません。確かに、この特定のケースに何かを実装するのは簡単かもしれませんが、それは他のすべてのケースにひどく役立つわけではありません。C ++委員会は、コンパイラー作成者にこれを要求しないことを単に決定しました。

于 2013-01-28T10:09:15.363 に答える