C++ 我可以避免在一系列函数调用中使用模板消歧器吗?

C++ 我可以避免在一系列函数调用中使用模板消歧器吗?,c++,c++11,templates,C++,C++11,Templates,我有一个模板生成器/工厂类,它生成Foo类型的对象,其中make()方法是一个模板方法,如下所示: template<typename T1> class FooMaker { template<typename T2> Foo make(...) { ... } }; 我想在上面构建Foo的每一行上都需要模板关键字。一般来说,我在每个FooMaker对象上都有许多对make()的调用,因此在创建工厂时添加少量代码就可以了 显然,我可以使用一个隐藏模板细节的宏来

我有一个模板生成器/工厂类,它生成
Foo
类型的对象,其中
make()
方法是一个模板方法,如下所示:

template<typename T1>
class FooMaker
{
  template<typename T2>
  Foo make(...) { ... }
};
我想在上面构建
Foo
的每一行上都需要
模板
关键字。一般来说,我在每个
FooMaker
对象上都有许多对
make()
的调用,因此在创建工厂时添加少量代码就可以了

显然,我可以使用一个隐藏
模板
细节的宏来实现这一点,但是否有一个好的非宏解决方案1


1我可以将
T1
T2
移动到相同的级别-通过使它们都成为类模板参数或函数模板参数,但是前者需要为每个新类型的
T2
指定一个不同的生成器,后者意味着在每个
make
调用中冗余指定相同的
T1

这是一个很大的原因,因为它是一个非成员函数,而不是
std::tuple
的成员。从该模式中汲取灵感,您可以创建一个非成员
make_foo

template <typename T2, typename T1, typename... Args>
Foo make_foo( FooMaker<T1>& maker, Args&& ... args ) {
    return maker.template make<T2>(std::forward<Args>(args)...);
}
模板
Foo make_Foo(FooMaker&maker,Args&;Args){
return maker.template make(std::forward(args)…);
}
然后像这样使用它:

auto maker = ...; // some code to construct the builder
Foo foo1 = make_foo<Type1>(maker, ...);
Foo foo2 = make_foo<Type2>(maker, ...);
// etc...
auto-maker=…;//构造生成器的一些代码
Foo foo1=make_Foo(制造商,…);
Foo Foo 2=制造者;
//等等。。。

您可以确保推导出
T2
。为此,你需要一个以某种方式提供信息的论点。这可能是一种简单的标记类型

template<typename T>
struct tag { using type = T; };

template<typename T1>
class FooMaker
{
  template<typename T2>
  Foo make_internal(...) { ... }
public:
  template<typename Tag>
  Foo make(Tag, ...)
  { return make_internal<Tag::type>(...); }
};

auto maker = ...; // some code to construct the builder
Foo foo1 = maker.make(tag<Type1>{}, ...);
Foo foo2 = maker.make(tag<Type2>{}, ...);
// etc...
模板
结构标记{using type=T;};
模板
职业美食家
{
模板
Foo make_internal(…){…}
公众:
模板
Foo make(标签…)
{返回make_internal(…);}
};
自动生成器=…;//构造生成器的一些代码
Foo foo1=maker.make(标记{},…);
Foo foo2=maker.make(标记{},…);
//等等。。。
或者枚举与traits类型组合,或者您可以简单地使用指针传入类型:

template<typename T1>
class FooMaker
{
public:
  template<typename T2>
  Foo make(T2*, ...);
};

auto maker = ...; // some code to construct the builder
Foo foo1 = maker.make((Type1*)0, ...);
Foo foo2 = maker.make((Type2*)0, ...);
// etc...
模板
职业美食家
{
公众:
模板
Foo-make(T2*,…);
};
自动生成器=…;//构造生成器的一些代码
Foo foo1=maker.make((Type1*)0,…);
Foo foo2=maker.make((Type2*)0;
//等等。。。

尽管可以说,这并不十分优雅。

如果
decltype(maker)
Type1
都不是依赖类型,我相信你可以编写
maker.make(…)。不过,我不确定它的确切规则。@Justin
Type1
始终是一个函数。但是,
decltype(maker)
独立意味着什么?这是否取决于T1的性质?有时
T1
是一个计划(非模板类),有时是一个模板类(但我可能会改变这个)。您可以使
make
成为一个独立函数,该函数将
Maker
作为一个参数,就像
std::tuple
getter一样。只有当
Maker
的类型不依赖时,您才能省略
模板,这意味着它不直接或间接依赖任何模板参数。(
Type1
对此不重要。)依赖类型只存在于模板定义中。@BeeOnRope完全正确。谢谢!这是否可以扩展到变量,而不是
template make(…)
我有
template make()
其中
func\u t
是一个函数typedef?@BeeOnRope在这种情况下,你不会传入functor
F
(可能是lambda)吗?也许你应该举个例子(或另一篇文章)。不,它总是一个普通函数,从来不是lambda或其他有状态的东西,比如
std::function
,所以我使用了模板函数参数特性,没有任何东西作为参数传递,但模板参数只是“直接调用”,例如,
typedef void(*func_t)(int);模板调用_f(/*无参数!*/){f(42);}
。你是对的,尽管这已经足够不同了,我也许应该提出一个新问题。
template<typename T1>
class FooMaker
{
public:
  template<typename T2>
  Foo make(T2*, ...);
};

auto maker = ...; // some code to construct the builder
Foo foo1 = maker.make((Type1*)0, ...);
Foo foo2 = maker.make((Type2*)0, ...);
// etc...