如果我有一点点代码......
template <typename _T>
class Foo
{
public:
typedef const T& ParamType;
void DoStuff(ParamType thingy);
};
如果sizeof(_T) <= sizeof(_T*)
,这可能不是最佳的。
因此,我希望有条件typedef
。如果_T
的大小小于或等于指针的大小,则只需将其传递给值。否则,通过const引用传递它。这可能吗?我听到所有这些关于模板完成图案的东西,但这让我头疼。
答案 0 :(得分:5)
使用partial template specialization非常容易实现。
template< typename _T, bool _ByVal >
struct FooBase {
typedef const _T& ParamType;
};
template< typename _T >
struct FooBase< _T, true > {
typedef const _T ParamType;
};
template< typename _T, bool _ByVal = sizeof(_T) <= sizeof(void*) >
class Foo : public FooBase< _T, _ByVal > {
typedef typename FooBase< _T, _ByVal >::ParamType ParamType;
void DoStuff(ParamType thingy);
};
编辑根据杰夫的解决方案,我应该确实比较sizeof(_T)
和sizeof(_T&)
,但我保留原来的<= void*
要求。
答案 1 :(得分:4)
你可以这样做,但这有点棘手。
我的主要关注点如果你的动机。我知道你不想按值传递大对象,但是对象是否大是无关紧要的 - 你真正想知道的是复制构造函数创建参数需要多长时间
作为一个具体的例子,std::vector
的大小实际上非常小,因为它分配堆上的所有内存并且只需要一个指针。但是,复制矢量需要更多时间。这样的事情不是你可以真正包含在条件中的东西。
这里最好的选择就是通过const &
以便覆盖最糟糕的情况。此外,我无法保证这一点,但我相信如果编译器认为更高效,那么编译器就足够聪明,可以通过值传递。
答案 2 :(得分:4)
template <class T, bool Smaller>
class BestArgumentPassingType {};
template <class T>
class BestArgumentPassingType<T, true> {
public:
typedef T Type;
};
template <class T>
class BestArgumentPassingType<T, false> {
public:
typedef const T& Type;
};
template <class T>
class ArgumentType : public BestArgumentPassingType<T, sizeof(T) < sizeof(T*)> {
};
struct B { double d; double d2; };
struct S { double d; };
class A {
public:
static void foo(ArgumentType<B>::Type big);
static void bar(ArgumentType<S>::Type small);
};
int main()
{
B b;
S s;
A::foo(b);
A::bar(s);
return 0;
}
喜欢这样。
答案 3 :(得分:3)
您可以使用Boost call traits。
template <typename _T>
class Foo
{
public:
void DoStuff(boost::call_traits<_T>::param_type thingy);
};
来自文档:
如果T是小型内置类型或指针,则param_type定义为T const,而不是T const&amp ;.
答案 4 :(得分:3)
我知道这不是你所要求的,但这是你的目标。我会用另一种方法来实现这一点:通过引用传递类(包括结构和联合),并按值传递其他所有内容。
template<typename>
struct tovoid { typedef void type; };
template<typename T, typename = void>
struct parm_type {
typedef T type;
};
template<typename T>
struct parm_type<T, typename tovoid<int T::*>::type> {
typedef T const& type;
};
template <typename T>
class Foo
{
public:
typedef typename parm_type<T>::type ParamType;
void DoStuff(ParamType thingy);
};
这实现了(在我看来)@Poita_做的非常好的观点。