簡體   English   中英

可變參數模板遞歸類型傳遞

[英]Variadic template recursive types passing

我在這里找到了幾乎令人滿意的解決方案(第二個答案),但是我不能在另一編譯單元中使用這種方式編寫的代碼,因為將代碼放入頭文件會導致鏈接器抱怨多個函數定義,而僅將聲明放在頭文件會導致鏈接器未定義的參考問題。

這是我的代碼:

template <typename... types>
void foo();

template<>
void foo<>() {
    return;
}

template<typename type, typename... types>
void foohelper() {
    foo<types...>();
}

template <typename... types>
void foo() {
    foohelper<types...>();
}

int main() {
    foo<int, int>();
}

這是我想要實現的目標:

class A {
public:
    template<>
    void foo<>() {
        return;
    }

    template<typename parser, typename... parsers>
    void foohelper() {
        foo<parsers...>();
    }

    template <typename... parsers>
    void foo() {
        foohelper<parsers...>();
    }
};

int main() {
    A a;
    a.foo<int, int>();
}

但這在編譯過程中導致以下錯誤:

explicit specialization 'void A::foo(void)' is not a specialization of a function template

有什么簡單的解決方案嗎?

無需遞歸。 這比較簡單:

#include <iostream>
#include <string>
#include <typeinfo>

class A {
public:

    template<typename parser>
    void foohelper() {
        std::cout << "handled a " << typeid(parser).name() << std::endl;
        // do work here
    }

    template <typename... parsers>
    void foo() {
        using expand = int[];
        (void) expand { 0, (foohelper<parsers>(), 0)... };
    }
};

int main() {
    A a;
    a.foo<int, int, double, std::string>();
}

樣本輸出:

handled a i
handled a i
handled a d
handled a NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE

編輯:

為了響應不符合要求的Microsoft編譯器的要求,這是另一個不依賴未調整大小數組的版本:

#include <iostream>
#include <string>
#include <typeinfo>

class A {
public:

    template<typename parser>
    void foohelper() {
        std::cout << "handled a " << typeid(parser).name() << std::endl;
        // do work here
    }

    template <typename... parsers>
    void foo() {
        // c++ strictly does not allow 0-sized arrays.
        // so here we add a NOP just in case parsers is an empty type list
        using expand = int[1 + sizeof...(parsers)];
        (void) expand {
            (foohelper<void>(), 0),
            (foohelper<parsers>(), 0)...
        };
    }

};

// implement the NOP operation. Note specialisation is outside class definition.
template<> void
A::foohelper<void>() {}



int main() {
    A a;
    a.foo<int, int, double, std::string>();
    a.foo<>();
}

編輯2:

帶有前綴,后綴和解析器間標注的完整示例。 編寫了這么多代碼之后,您可能會開始思考:“嘿!我可以在這里實現整個領域特定的語言!”,您將是對的。

但是,復雜性遠不止於此,這可能會使您對同事產生永恆的仇恨,因此,我將避免走這條路。

#include <iostream>
#include <string>
#include <typeinfo>

class A {
public:

    template<typename parser>
    void foohelper() {
        std::cout << "handled a " << typeid(parser).name();
        // do work here
    }

    void prepare()
    {
        std::cout << "starting parsers: ";
    }

    void separator()
    {
        std::cout << ", ";
    }

    void nothing()
    {

    }

    void done() {
        std::cout << " done!" << std::endl;
    }

    template <typename... parsers>
    void foo() {
        // c++ strictly does not allow 0-sized arrays.
        // so here we add a NOP just in case parsers is an empty type list
        bool between = false;
        using expand = int[2 + sizeof...(parsers)];
        (void) expand {
            (prepare(), 0),
            ((between ? separator() : nothing()), between = true, foohelper<parsers>(), 0)...,
            (done(), 0)
        };
    }

};


int main() {
    A a;
    a.foo<int, int, double, std::string>();
    a.foo<>();
}

樣本輸出:

starting parsers: handled a i, handled a i, handled a d, handled a NSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEE done!
starting parsers:  done!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM