如何限制c ++ 11中的参数包类型?以及如何在cpp中实现模板?

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

对于第一个问题:

我想编写一个连接字符串的函数,它可以接收多个字符串;

#include <string>
#include <vector>
#include <type_traits>

template <class... Args, typename std::enable_if<std::is_same<typename std::decay<Args...>::type, std::string>::type>::type>
std::string foo(const std::string &first, const Args &... senconds) {
    std::string delimiter = "$$";
    std::string ret = first;
    std::vector<std::string> vec{senconds...};
    for (auto second = vec.rbegin(); second != vec.rend(); second++) {
        ret = delimiter + *second + delimiter + ret;
    }
    return ret;
}

但是当我像这样调用它时:

std::string name = "x";
name = foo(name, "xxx");

编译器将抛出错误:

error: no matching function for call to ‘foo(std::__cxx11::string&, const char [4])’

并且会有一些注释:

note: couldn't deduce template parameter ‘<anonymous>’

[我认为我应该修改模板中的约束,并且我已经尝试了type_traits中的所有相关方法,但是它们都不起作用。

第二个问题:

我想隐藏某些函数的实现,但是对于模板函数,它无法将定义放入.hpp中,而无法将实现放入.cpp中,编译器将抛出undefined reference错误。有什么优雅的方法可以解决这个问题吗?

谢谢。

c++11 parameter-passing variadic-templates
2个回答
1
投票

这里有些东西要解开。

  • std::decay<Args...>::type无法工作。 std::decay仅接受单个模板参数,但是您尝试在此处扩展包。扩展需要在is_same上进行。

  • 您还缺少一种汇总所有is_same谓词的方法。您要全部and还是全部or?大概是and。在C ++ 17中,使用fold表达式可以轻松完成此操作,但是对于C ++ 11,我们必须花点功夫。

  • 最后,编译器会抱怨:如果std::enable_if<bla>::typevoid,则bla的值为true。这意味着您正式希望使用非类型的模板参数,并且编译器会抱怨,因为它无法推断应推导哪种类型的void值。通常可以通过形成指向它的指针并将其默认设置为nullptrstd::enable_if<bla>::type* = nullptr来缓解此问题。

  • 您似乎期望(C0)起作用(?)。不会,因为字符串文字不是foo(someString, "stringLiteral");。也许您想要一个不同的谓词,但是对于这个答案,我将坚持原始条件。


将所有内容放在一起:

  • 在C ++ 17中,您会写

    std::string

    template <class... Args, std::enable_if_t< (std::is_same_v<std::decay_t<Args>, std::string> && ...) >* = nullptr >

  • 在C ++ 11中,我们使用https://godbolt.org/z/84Dcmt帮助程序,并添加thistypename详细程度:

    ::type

    template <class... Args, typename std::enable_if< var_and< std::is_same<typename std::decay<Args>::type, std::string>::value... >::value >::type* = nullptr >


0
投票

基于https://godbolt.org/z/2eFyX7,我将模板更改为:

MaxLanghof's answer

以这种形式,可以像template <class... Args, typename std::enable_if<var_and<std::is_constructible< std::string, Args>::value...>::value>::type * = nullptr> 一样调用功能foo

再次感谢@MaxLanghof。

© www.soinside.com 2019 - 2024. All rights reserved.