簡體   English   中英

可變參數 function 模板中的模糊模板專業化

[英]ambiguous template specialization in variadic function template

我正在嘗試編寫一個可變參數 function 模板來計算struct的字節大小。 這將用於我正在從事的網絡編程項目。 第一步我想出了這個沒有可變參數模板的工作:

#include <cstdint>
#include <iostream>

struct Position
{
    int32_t x;
    int32_t y;
};

template<typename T>
inline std::size_t sizeT() { return sizeof(T); }

template<>
inline std::size_t sizeT<Position>() { return sizeT<int32_t>() + sizeT<int32_t>(); }
// if I change the definition of Position, I need to remember to change this function

int main(int argc, char* argv[])
{
    std::cout << "int8_t:" << sizeT<int8_t>() << std::endl;
    std::cout << "Position:" << sizeT<Position>() << std::endl;

    return 0;
}

我在我的Ubuntu 20.04筆記本電腦上使用g++ 9.3.0編譯,它運行良好。 但是,如果我嘗試將其設為可變參數模板,則會遇到不同的編譯錯誤。 這個可變參數模板的重點是能夠像下面這樣編寫,以便實現不依賴於xy類型的顯式知識。

這是錯誤的代碼#1

#include <cstdint>
#include <iostream>

struct Position
{
    int32_t x;
    int32_t y;
};

template<typename T>
inline std::size_t sizeT() { return sizeof(T); }

template<>
inline std::size_t sizeT<Position>()
{
    return sizeT<decltype(Position::x), decltype(Position::y)>();
}

template<>
inline std::size_t sizeT<Position>() { return sizeT<int32_t>() + sizeT<int32_t>(); }


int main(int argc, char* argv[])
{
    std::cout << "int8_t:" << sizeT<int8_t>() << std::endl;
    std::cout << "Position:" << sizeT<Position>() << std::endl;

    return 0;
}

我有

錯誤:'std::size_t sizeT() 的模版特化 'sizeT' 模棱兩可

注意:候選者是:'template std::size_t sizeT()'

注意:模板<class T, class... Ts> std::size_t sizeT()'

錯誤代碼 #2。 如果我將可變參數模板放在不同的位置:

#include <cstdint>
#include <iostream>

struct Position
{
    int32_t x;
    int32_t y;
};

template<typename T>
inline std::size_t sizeT() { return sizeof(T); }

template<>
inline std::size_t sizeT<Position>() { return sizeT<int32_t>() + sizeT<int32_t>(); }


template<>
inline std::size_t sizeT<Position>()
{
    return sizeT<decltype(Position::x), decltype(Position::y)>();
}

int main(int argc, char* argv[])
{
    std::cout << "int8_t:" << sizeT<int8_t>() << std::endl;
    std::cout << "Position:" << sizeT<Position>() << std::endl;

    return 0;
}

我有

錯誤:重載 'sizeT<int8_t>()' 的調用不明確

注意候選:'std::size_t sizeT() [with T=signed char; std::size_t = long unsigned int]'

注意候選:'std::size_t sizeT() [with T=signed char; TS={}; std::size_t = long unsigned int]'

錯誤:重載 'sizeT()' 的調用不明確

注意候選:'std::size_t sizeT() [with T=Position; std::size_t = long unsigned int]'

注意候選:'std::size_t sizeT() [with T=Position; TS={}; std::size_t = long unsigned int]'

我有點理解案例#2,但我不明白#1。 我怎樣才能做到這一點? 非常感謝你。

你不使用可變參數...

你可能會做 (C++17)

template <typename ... Ts>
constexpr std::size_t sizeT() { return (0 + ... + sizeof(Ts)); }

template <>
constexpr std::size_t sizeT<Position>()
{
    return sizeT<decltype(Position::x), decltype(Position::y)>();
}

演示

但是sizeT<Position, Position>將返回2 * sizeof(Position)而不是2 * sizeT<Position> (這里是相同的)。

你可能會這樣做:

template <typename... Ts>
struct tag{};

template <typename T>
constexpr std::size_t sizeT(tag<T>) { return sizeof(T); }

template <typename ... Ts>
constexpr std::size_t sizeT(tag<Ts...>) { return (0 + ... + sizeT(tag<Ts>())); }

template <typename ... Ts>
constexpr std::size_t sizeT(tag<Ts>...) { return (0 + ... + sizeT(tag<Ts>())); }

constexpr std::size_t sizeT(tag<Position>)
{
    return sizeT(tag<decltype(Position::x), decltype(Position::y)>());
}

演示

暫無
暫無

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

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