根据类型特征专门化 C++11 模板,同时允许其他类型的回退

问题描述 投票:0回答:1

我目前正在致力于将多个数据结构序列化为 JSON。

现有的数据结构已经提供了基于文本的输出格式,当将特定类型转换为 JSON 的函数尚不存在时,我想将其用作默认格式。

我目前已经完成了后备和几个特定的专业化。由于我使用的 JSON 库已经能够使用 int、float 等基元,无需任何额外的工作,我希望这些类型有自己的(通用)专用模板函数。

我当前的主要问题是我无法让

to_json(1)
调用基础/基元的函数,但如果我手动指定类型(
to_json<int>
),则会调用正确的函数。有没有什么办法解决这一问题?编译器在第一行推导出什么类型?

我仅限于 C++11。

以下总结了我的基本设置


#include <iostream>
#include <type_traits>

// Should rely on fallback
struct S {
};

// Has specialization
struct R {
};


// Fallback. Should catch everything not caught by the specializations
template <typename T>
void to_json(const T& x);


// Specialization for R
template<>
void to_json(const R& x)
{
    std::cout << "For R\n";
}

// Does not work
// Specialization for all fundamentals (e.g. int)
template<typename T>
void to_json(const typename std::enable_if<std::is_fundamental<T>::value, T>::type& x)
{
    std::cout << "For fundamentals\n";
}

template <typename T>
void to_json(const T& x)
{
    std::cout << "General\n";
}

int main()
{
    to_json(1);      // General. (WRONG, expected fundamentals)
    to_json<int>(1); // fundamentals (CORRECT)
    to_json(R{});    // R (CORRECT)
    to_json(S{});    // General (CORRECT)

    return 0;
}

输出:

General
For fundamentals
For R
General
c++11 templates overloading fallback type-deduction
1个回答
0
投票

您的前向声明模板函数将捕获所有类型。使用具体类型初始化时会遇到麻烦。

//// Fallback. Should catch everything not caught by the specializations
//template <typename T>
//void to_json(const T& x);

下面的代码应该可以正常工作:

// Should rely on fallback
struct S {
};

// Has specialization
struct R {
};

// note: also use enable_if_t to exclude fundamental type
//       otherwise compiler is still confused by the redefinition
template <typename T,
        std::enable_if_t<!std::is_fundamental<T>::value, bool> = true>
void to_json(const T& x)
{
    std::cout << "General\n";
}
    
// Specialization for R
template<>
void to_json(const R& x)
{
    std::cout << "For R\n";
}

// Specialization for all fundamentals (e.g. int)
template<typename T,
         std::enable_if_t<std::is_fundamental<T>::value, bool> = true>
void to_json(const T& x)
{
    std::cout << "For fundamentals\n";
}

int main()
{
    to_json(1);      // General. (WRONG, expected fundamentals)
    to_json<int>(1); // fundamentals (CORRECT)
    to_json(R{});    // R (CORRECT)
    to_json(S{});    // General (CORRECT)

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.