在部分特化中模拟默认模板参数是否可行?

7

默认模板参数可以在模板声明中用来模拟复杂类型表达式的别名。例如:

template <typename X,
          typename Y = do_something_with<X>::type,
          typename Z = some_other_thing_using<X, Y>::type
struct foo { ... X, Y, Z ... };

然而,部分特化可能没有默认的模板参数([C++11: 14.5.5/8]),所以这个技巧不适用。你可能会问为什么在类体中的 typedef 不起作用,答案是别名需要在类体之前就在作用域内,以进行条件启用;例如:

template <typename T, typename Enable = void>
struct bar;

// Wishful thinking:
template <typename X,
          typename Y = do_something_with<X>::type,
          typename Z = some_other_thing_using<X, Y>::type>
struct bar <std::vector<X>,
            typename enable_if<
                some_condition<X, Y, Z>
            >::type>
    { ... };

我解决它的方法是使用一个辅助类型:
template <typename X>
struct bar_enabled {
    typedef typename do_something_with<X>::type Y;
    typedef typename some_other_thing_using<X, Y>::type Z;
    static const bool value = some_condition<X, Y, Z>::value;
};

template <typename X>
struct bar <std::vector<X>,
            typename enable_if_c<
                bar_enabled<X>::value
            >::type>
    { ... };

但由于各种原因(其中包括想要避免使用单独的类型,这会使我正在做的事情变得更加复杂),我希望存在更好的解决方案。有什么想法吗?


1
默认参数并不模拟任何东西,它们只是提供默认值。 - Kerrek SB
4
记录一下, "一个特化的模板参数列表不应包含默认的模板参数值" [C++11: 14.5.5/8] - Lightness Races in Orbit
@LightnessRacesinOrbit,你是在指出这个问题在C++11中没有改变,还是别的什么? - ajg
@AJG:为您的正确声明附上引用。 - Lightness Races in Orbit
1个回答

4
也许你可以将这个区分放入基类中:
template <typename X, typename Y, bool>
struct BaseImpl             { /* ... */ };

template <typename X, typename Y>
struct BaseImpl<X, Y, true> { /* ... */ };

template <typename X, typename Y = typename weird_stuff<X>::type>
struct Foo : BaseImpl<X, Y, some_condition<X, Y>::value>
{
    // common stuff
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接