c++ 有没有可能让一个模板函数使用转换或演绎向导来演绎模板参数的类型?

xqkwcwgp  于 2023-03-14  发布在  其他
关注(0)|答案(2)|浏览(124)

是否有可能让编译器使用类型转换或演绎指南来演绎模板函数调用的类型?如果没有,原因是什么?

#include <iostream>

template<typename T>
class Wrapper
{
public:
    Wrapper(T&& elmt)
        : m_data(std::forward<T>(elmt))
    {   }

    const T& data() const
    {
        return m_data;
    }

private:
    T m_data;
};

template<typename T>
Wrapper(T&& elmt) -> Wrapper<T>;

template<typename T>
void someFunc(const Wrapper<T>& wrapper)
{
    std::cout << wrapper.data() << std::endl;
}

int main()
{
    // Any chance this could work?
    // someFunc("Make me a Wrapper<const char*> please!");     //fails
    // someFunc({"Make me a Wrapper<const char*> please!"});   //fails

    // This works, but that's what I'd like to avoid
    someFunc(Wrapper{"This one works"});

    return 0;
}

(编译器资源管理器链接:https://godbolt.org/z/eGs3raMY4
如果Wrapper不是模板,则可以直接执行以下操作:

#include <iostream>

class StrWrapper
{
public:
    StrWrapper(const char* str)
        : m_data(str)
    {   }

    const char* data() const { return m_data; }

private:
    const char* m_data;
};

void strFunc(const StrWrapper& wrapper)
{
    std::cout << wrapper.data() << std::endl;
}

int main()
{
    strFunc("This works, right?");

    return 0;
}

(编译器资源管理器:https://godbolt.org/z/nnoaPcs91
我知道我可以为每种类型添加一个重载,但是在这种情况下,这不是一个非常实用的解决方案(需要许多重载)。

0s0u357o

0s0u357o1#

有没有可能让编译器使用类型转换或推导指南来推导模板函数调用的类型?
你可以用递归的方法

// variable template for checking the "Wrapper<T>" type
template<typename T> inline constexpr bool is_Wrapper = false;
template<typename T> inline constexpr bool is_Wrapper<Wrapper<T>> = true;

template<typename T>
void someFunc(T&& arg)
{
    if constexpr (is_Wrapper<T>)  // if T == Wrapper<T>
        std::cout << arg.data() << std::endl;
    else  // if T != Wrapper<T>, construct explicitly and pass to the someFunc()
        someFunc(Wrapper<T>{ std::forward<T>(arg) });
}

这允许两者

someFunc("Make me a Wrapper<const char*> please!");  // works
someFunc(Wrapper{ "This one works" });               // works

See a live demo in godbolt.org

6ovsh4lw

6ovsh4lw2#

您可以让someFunc接受 Package 器,然后在函数内部构造 Package 器,如下所示

template<typename T>
void someFunc(T&& to_wrap)
{
    Wrapper wrapper{std::forward<T>(to_wrap)};
    std::cout << wrapper.data() << std::endl;
}

它允许

someFunc("Make me a Wrapper<const char*> please!");

live example所示进行编译。
原因是

someFunc("Make me a Wrapper<const char*> please!");
someFunc({"Make me a Wrapper<const char*> please!"});

失败的原因是它们不是Wrapper的,并且编译器不会尝试转换参数,因此编译器无法推断T应该是什么。

相关问题