我想创造一些宏来创建模板参数传递,存储,等我使用类模板参数推导静态接口,但我打墙。
#include <iostream>
template <typename Type>
struct Person
{
Type &object;
Person(Type &object) : object(object) {}
void walk(unsigned steps)
{
object.walk(steps);
}
void talk(const std::string &words)
{
object.talk(words);
}
};
struct MySelf
{
void walk(unsigned steps)
{
std::cout << "walking: " << steps << std::endl;
}
void talk(const std::string &words) const
{
std::cout << "talking: " << words << std::endl;
}
};
template <typename Type>
void testNConst(Person<Type> object)
{
object.walk(50);
object.talk("testing");
}
template <typename Type>
void testConst(Person<const Type> object)
{
object.talk("testing");
}
int main()
{
MySelf myself;
testNConst(Person{myself}); // compiles
testNConst(myself); // does not compile
testConst(myself); // does not compile
return 0;
}
输出:
../../../../src/py.com.personal/other/hanaTest/main.cpp:53:5: error: no matching function for call to 'testNConst'
testNConst(myself); // does not compile
^~~~~~~~~~
../../../../src/py.com.personal/other/hanaTest/main.cpp:35:6: note: candidate template ignored: could not match 'Person<type-parameter-0-0>' against 'MySelf'
void testNConst(Person<Type> object)
^
../../../../src/py.com.personal/other/hanaTest/main.cpp:54:5: error: no matching function for call to 'testConst'
testConst(myself); // does not compile
^~~~~~~~~
../../../../src/py.com.personal/other/hanaTest/main.cpp:42:6: note: candidate template ignored: could not match 'Person<const type-parameter-0-0>' against 'MySelf'
void testConst(Person<const Type> object)
^
2 errors generated.
有什么想法吗?
答案 0 :(得分:2)
类模板自变量推导仅适用于创建对象(变量声明等)。
不仅适用于函数参数或函数返回类型。您无法调用testNConst(myself)
,因为对于某些myself
来说Person<T>
不是T
-适用常规函数推导规则。
简而言之:
template <typename T> struct X { X(T ); };
X x = 42; // ok, ctad here
template <typename T>
void foo(X<T> );
foo(42); // error, ctad doesn't apply here
X bar() { return 42; } // error, ctad doesn't apply here either
答案 1 :(得分:0)
另一种方法可能是使用curiously recurring template pattern (CRTP),它从接口继承,该接口将类型本身作为模板参数,请记住,您可以使用static_cast进行下转换,并且使用接口时,重载解析没有问题作为参数。您必须知道您不能使用Person类型的对象(如果未子类化)。因此,您必须通过引用将对象传递给函数(比复制对象要快)。
接口不是驻留在Person内部的Type类型的对象,而是驻留在Type本身内部。 (接口没有任何成员,当从空结构继承时,没有额外的内存开销,MySelf的大小与没有继承的情况相同)。使用这种方法,切勿在参数列表中没有Person<Type>
,const&
或&
的情况下使用&&
。
#include <iostream>
template <typename Type>
struct Person
{
/// this returns the subclass-object
Type &object() { return static_cast<Type&>(*this); }
Type const &object() const { return static_cast<Type const&>(*this); }
void walk(unsigned steps)
{
object().walk(steps);
}
void talk(const std::string &words) const /// const was eventually missing
{
object().talk(words);
}
protected:
~Person() = default; /// this disallows the user to construct an instance of this class that is not used as a base object
};
struct MySelf : Person<MySelf>
{
void walk(unsigned steps)
{
std::cout << "walking: " << steps << std::endl;
}
void talk(const std::string &words) const
{
std::cout << "talking: " << words << std::endl;
}
};
template <typename Type>
void testNConst(Person<Type>& object) /// works fine with instances of MySelf and Person<MySelf>
{
object.walk(50);
object.talk("testing");
}
template <typename Type>
void testConst(Person<Type> const& object)
{
object.talk("testing");
}
int main()
{
MySelf myself;
testNConst(myself); // compiles
testConst(myself); // compiles
return 0;
}
static_cast<Type&>
是关键点)。