C++ 具有可变模板参数的重载函数
我想将一些代码从使用重载函数转换为使用可变模板参数 对于不同的参数计数,现有代码具有多个模板函数:C++ 具有可变模板参数的重载函数,c++,c++11,C++,C++11,我想将一些代码从使用重载函数转换为使用可变模板参数 对于不同的参数计数,现有代码具有多个模板函数: #include <iostream> #include <string> struct Boo { Boo(const std::string& name) { std::cout << "Boo constructor: " << name << std::endl; };
#include <iostream>
#include <string>
struct Boo
{
Boo(const std::string& name)
{
std::cout << "Boo constructor: " << name << std::endl;
};
static std::string CreateName(const std::string& name)
{
return "BooID:" + name;
}
};
struct Foo
{
Foo(const std::string& name)
{
std::cout << "Foo constructor: " << name << std::endl;
};
};
template <typename T>
T Construct(const std::string& name)
{
return T(T::CreateName(name));
}
template <typename T>
T Construct(const std::string& name1, const std::string& name2)
{
return T(T::CreateName(name1, name2));
}
// Class Foo doesn't have CreateName available
template<>
Foo Construct<Foo>(const std::string& name)
{
return Foo{"ID:" + name};
}
int main()
{
Construct<Boo>(std::string("123"));
Construct<Foo>(std::string("456"));
}
如果我试图将两个模板化的Construct()
函数替换为一个单变量模板化版本,那么我无法确定如何仅为Foo
类指定特殊版本(在GCC 4.9.2、8.1和Visual Studio 2015上试用)
我可以通过制作一个通用模板并使用std::enable_if_t
来限制类型,从而使其正常工作:
template <class T, typename ...Args>
T Construct(Args... args)
{
return T(T::CreateName(args...));
}
// Class Foo needs some extra information when constructed with strings...
template<typename T, typename = std::enable_if_t<std::is_base_of<Foo, T>::value>>
T Construct(const std::string& name)
{
return T{"ID:" + name};
}
模板
T构造(Args…Args)
{
返回T(T::CreateName(args…);
}
//类Foo在使用字符串构造时需要一些额外的信息。。。
模板
T构造(const std::string和name)
{
返回T{“ID:+name};
}
它不像原始的
模板Foo-Construct(…)
版本那么容易阅读。使用变量模板的std::enable\u if\u t
是唯一的选项,还是有某种重载方式可以提供所需的行为?这里的问题是专门化必须与基本模板匹配
您的基本模板将被推断为构造
,您的专业化必须与此匹配才能被视为有效
如果您将专门化更改为
template<>
Foo Construct<Foo, std::string>(std::string name)
{
return Foo{"ID:" + name};
}
模板
Foo构造(std::string name)
{
返回Foo{“ID:+name};
}
它可以正常工作。这里的问题是专门化必须与基本模板匹配 您的基本模板将被推断为
构造
,您的专业化必须与此匹配才能被视为有效
如果您将专门化更改为
template<>
Foo Construct<Foo, std::string>(std::string name)
{
return Foo{"ID:" + name};
}
模板
Foo构造(std::string name)
{
返回Foo{“ID:+name};
}
它可以正常工作。问题在于不能部分专门化模板函数 我建议使用模板方法
func()
模板
struct Constr
{
template <typename ... Args>
static T func (Args const & ... names)
{ return T(T::CreateName(names...)); }
};
template <>
struct Constr<Foo>
{
static Foo func (std::string const & name)
{ return Foo{"ID:" + name}; }
};
struct Constr
{
模板
静态T函数(参数常量和…名称)
{返回T(T::CreateName(names…);}
};
模板
结构施工
{
静态Foo func(std::string const&name)
{返回Foo{“ID:+name};}
};
电话变成了电话
Constr<Boo>::func(std::string("123"));
Constr<Foo>::func(std::string("456"));
Constr::func(std::string(“123”);
Constr::func(std::string(“456”);
问题在于不能部分专门化模板函数
我建议使用模板方法func()
模板
struct Constr
{
template <typename ... Args>
static T func (Args const & ... names)
{ return T(T::CreateName(names...)); }
};
template <>
struct Constr<Foo>
{
static Foo func (std::string const & name)
{ return Foo{"ID:" + name}; }
};
struct Constr
{
模板
静态T函数(参数常量和…名称)
{返回T(T::CreateName(names…);}
};
模板
结构施工
{
静态Foo func(std::string const&name)
{返回Foo{“ID:+name};}
};
电话变成了电话
Constr<Boo>::func(std::string("123"));
Constr<Foo>::func(std::string("456"));
Constr::func(std::string(“123”);
Constr::func(std::string(“456”);
不要专门化函数模板。最简单的方法是遵循类模板:
template <typename T, typename... Args>
T Construct(Args&&... args) {
return ConstructorImpl<T>::apply(std::forward<Args>(args)...);
}
(虽然这不会检查它是否实际返回
t
)不要专门化函数模板。最简单的方法是遵循类模板:
template <typename T, typename... Args>
T Construct(Args&&... args) {
return ConstructorImpl<T>::apply(std::forward<Args>(args)...);
}
(尽管这不会检查它是否实际返回了
t
)看起来您尝试的专门化应该是Foo-Construct
@SamVarshavchik-我忘了提到我已经尝试过了,我会更新。谢谢。看起来你尝试的专门化应该是Foo-Construct
@SamVarshavchik-我忘了提到我尝试过,我会更新的。谢谢。如果你不能部分专门化一个模板函数,那就完全专门化它。比我的解决方案更好。如果你不能部分专门化一个模板函数,就完全专门化它。比我的解决方案好。
template <typename T, typename... Args>
auto Construct(Args&&... args)
-> decltype(ConstructorImpl<T>::apply(std::forward<Args>(args)...))
{
return ConstructorImpl<T>::apply(std::forward<Args>(args)...);
}