带有别名的 Variadic 模板扩展?

Variadic template expansion with aliases?

所以在我继承的代码库中,我们有一个混乱的实用程序文件,大致如下:

template <typename T, std::enable_if_t<(sizeof(T) == 1)>> int doA(const T *Data, size_t Size);
template <typename T, std::enable_if_t<(sizeof(T) == 1)>> int doB(const T *Data, size_t Size);

template <typename T> int doA(T &Input) 
{ return doA<uint8_t>((uint8_t *)&Input, sizeof(T); };
template <typename T, size_t N> int doA(T(&Input)[N]) 
{ return doA(Input, N - 1); };

template <typename T> int doA(std::vector<T> Input) 
{ return doA((uint8_t *)Input.data(), sizeof(T::value_type) * Input.size()); };
/* Repeat for doB */

所以我认为由于 doAdoB 非常相似,所以可以将混乱减少为:

template <bool TypeA, typename T, std::enable_if_t<(sizeof(T) == 1)>> 
int do_t(const T *Data, size_t Size) { if constexpr(TypeA) ... };

template <bool TypeA, typename T> int do_t(T &Input) 
{ return do_t<TypeA, uint8_t>((uint8_t *)&Input, sizeof(T); };
template <bool TypeA, typename T, size_t N> int do_t(T(&Input)[N]) 
{ return do_t<TypeA, T>(Input, N - 1); };

template <bool TypeA, typename T> int do_t(std::vector<T> Input) 
{ return do_t<TypeA, uint8_t>((uint8_t *)Input.data(), sizeof(T::value_type) * Input.size()); };

template <typename ...Args> using doA = do_t<true, Args...>;
template <typename ...Args> using doB = do_t<false, Args...>;

// Expand to do_t<true, char, 4>(char (&Input)[4])
static_assert(doA("abc") == 123);

// Expand to do_t<false, int>(int &Input)
static_assert(doB(321) == 123);

自然地,编译器抱怨 do_t 在别名处未定义,这并没有解决。在您想要捕获所有重载的情况下,正确的方法是什么?

我想,您可以编写几个 C 风格的宏,而不是您的几个 using 声明。

但我认为 C 风格的宏是邪恶的提炼物,所以我提出了两个简单的转换函数

template <typename ... Args>
auto doA (Args && ... as)
 { return do_t<true>(std::forward<Args>(as)...); }

template <typename ... Args>
auto doB (Args && ... as)
 { return do_t<false>(std::forward<Args>(as)...); }

或者,您可以使用函子对象:

template <bool isA>
struct doT
{
    template <typename T, std::enable_if_t<(sizeof(T) == 1), int> = 0> 
    int operator()(const T *Data, size_t Size) const
    {
        if constexpr (isA) { return doA_impl(Data, Size); }
        else { return doB_impl(Data, Size); }
    }

    template <typename T>
    int operator() (T &Input) const
    { return (*this)((std::uint8_t *)&Input, sizeof(T)); }

    template <typename T, size_t N>
    int operator() (T(&Input)[N]) const
    { return (*this)(Input, N - 1); }

    template <typename T>
    int operator() (std::vector<T> Input) const
    { return (*this)((std::uint8_t *)Input.data(), sizeof (T::value_type) * Input.size()); };
};

constexpr doT<true> doA{};
constexpr doT<false> doB{};

注意:ADL 不适用于与常规函数相反的仿函数对象。