Sfinae如何工作

How does SFINAE exactly work?

本文关键字:工作 何工作 Sfinae      更新时间:2023-10-16

我对Sfinae有问题。我缺少重要的东西,阅读其他问题无济于事:(

这是代码:

#include <string>
#include <type_traits>
#include <iostream>
// version with template class
template<typename T, typename = std::enable_if_t<
                std::is_integral<std::remove_reference_t<T>>::value
             || std::is_floating_point<std::remove_reference_t<T>>::value
             >
         >
struct to_my_string
{
    std::string operator()(T numerical)
    {
        return std::to_string(numerical);
    }
};
template<typename T, typename = std::enable_if_t< std::is_same<T, std::string>::value > >
struct to_my_string
{
    std::string operator()(T str)
    {
        return "'" + str + "'";
    }
};

// version with template method
template<typename T, typename = std::enable_if_t<
                std::is_integral<std::remove_reference_t<T>>::value
             || std::is_floating_point<std::remove_reference_t<T>>::value
             >
         >
std::string to_string_method(T numerical)
{
    return std::to_string(numerical);
}
template<typename T, typename = std::enable_if_t< std::is_same<T, std::string>::value > >
std::string to_string_method(T str)
{
    return "'" + str + "'";
}
int main()
{
    std::cout << "start" << std::endl;
    return 0;
}

我粘贴了两种方法 - 一种类和一种方法方法。两者都产生类似的错误:这是G 的错误(Clang给出了类似的错误(:

g++ --std=c++14 sfinae_failure.cpp
sfinae_failure.cpp:21:12: error: redefinition of default argument for ‘class<template-parameter-1-2>’
 struct to_my_string
        ^
sfinae_failure.cpp:7:26: note: original definition appeared here
 template<typename T, typename = std::enable_if_t<
                      ^
sfinae_failure.cpp:43:17: error: redefinition of ‘template<class T, class> std::__cxx11::string to_string_method(T)’
 std::string to_string_method(T str)
             ^
sfinae_failure.cpp:37:17: note: ‘template<class T, class> std::__cxx11::string to_string_method(T)’ previously declared here
 std::string to_string_method(T numerical)
             ^

我的主要问题是,即使我在enable_if_t中使用t type,它也为什么不起作用。我想念什么?

其他侧面问题是 - 我认为使用模板类/方法是在使用时实例化的。正如您在主要方法中看到的那样 - 它们不是。

,即使在很多次触及了这个话题的情况下,我真的很感谢您的帮助...

类模板的错误是因为您无法重新定义类模板,它与Sfinae无关。

template<class A = int> struct foo {};
template<class A = double> struct foo {};

即使没有实例化也无法编译此代码。

您函数的错误是因为默认模板参数是不是函数模板参数签名的一部分。

template<class A, class B = int> void bar() {}
template<class A, class B = double> void bar() {}

即使没有实例化,此代码也无法编译,因为它们的模板参数签名是相同的:

template<class A, class B> void bar() {}

因此重新定义。

修复版本:

template<typename T, typename Enabler = void> struct to_my_string;
template <typename T>
struct to_my_string<T, std::enable_if_t<
                std::is_integral<std::remove_reference_t<T>>::value
             || std::is_floating_point<std::remove_reference_t<T>>::value
             >>
{
    std::string operator()(T numerical) const
    {
        return std::to_string(numerical);
    }
};
template<typename T>
struct to_my_string<T, std::enable_if_t<std::is_same<T, std::string>::value>>
{
    std::string operator()(const T& str) const
    {
        return "'" + str + "'";
    }
};

// version with template method
template<typename T, std::enable_if_t<
                std::is_integral<std::remove_reference_t<T>>::value
             || std::is_floating_point<std::remove_reference_t<T>>::value
             , void*> = nullptr
         >
std::string to_string_method(T numerical)
{
    return std::to_string(numerical);
}
template<typename T, std::enable_if_t< std::is_same<T, std::string>::value, void*> = nullptr>
std::string to_string_method(T str)
{
    return "'" + str + "'";
}