【问题标题】:Is it possible to use tag dispatching to determine return type是否可以使用标签调度来确定返回类型
【发布时间】:2012-08-20 23:23:25
【问题描述】:

Switch passed type from template 中提到了标签调度。

是否有可能(以及如何)做类似的事情:

struct Tag1 {};
struct Tag2 {};

template<class T, typename R>
R get();

template<>
double get<Tag1>() {return 1.3;}

template<>
char const *get<Tag2>() {return "hello";}

double aDouble = get<Tag1>();
char const *aString = get<Tag2>();

上面的代码导致编译器抱怨对重载函数的模糊调用,但我希望最后两行传达使用意图。

谢谢

【问题讨论】:

  • “有可能”是什么意思?为什么不?我不明白你在问什么。
  • 有什么问题? (而不是 Tag1,Tag2 我会简单地使用 double 和 char const* 但你可能有你的理由)。
  • 是的,我有返回类型工作的情况,我只是想知道边界在哪里。

标签: c++ templates


【解决方案1】:

您可以使用 std::enable_ifstd::is_same (C++11),或者它们的 boost 等价物:

template <typename Tag>
typename std::enable_if<std::is_same<Tag, Tag1>::value, double>::type get()
{ ... }

template <typename Tag>
typename std::enable_if<std::is_same<Tag, Tag2>::value, char const *>::type get()
{ ... }

【讨论】:

  • 我不知道(我使用 gcc/clang),你必须检查一下。
  • 如果没有,请使用 boost -- 或者,您可以自己编写 enable_if 和 is_same 代码(这两个人并不难)。
【解决方案2】:

具有不同数量模板参数的函数模板会相互重载,因此您定义的不是特化而是重载。像这样的东西应该可以工作:

struct Tag1 {};
struct Tag2 {};

template<class T> struct MapResult;

template<> struct MapResult<Tag1> { typedef double Result; };
template<> struct MapResult<Tag2> { typedef char const* Result; };

template<class T>
typename MapResult<T>::Result get();

template<> double get<Tag1>() {return 1.2;}
template<> char const *get<Tag2>() {return "hello";}

【讨论】:

    【解决方案3】:

    get 的第二个模板参数无法推断,因为它仅作为返回类型出现:谁说get&lt;Tag1&gt;() 是专门对get&lt;Tag1, double&gt; 的调用,而不是例如。 get&lt;Tag1, int&gt;?如果你打电话给例如get&lt;Tag1, double&gt;() 然后调用将被解析为正确的专业化。

    但是我怀疑您并不真的希望 get 成为具有两个模板参数的函数模板:返回类型可能是第一个参数的函数。因此,我建议您像这样声明get

    namespace result_of {
    
    template<typename T>
    struct get;
    
    }
    
    template<typename T>
    typename result_of::get<T>::type get();
    

    其中result_of::get 将是计算预期结果类型的元函数。为了让事情更简单,我们将把所有的鸡蛋都放在result_of::get 篮子里,而不是专门针对函数模板get

    namespace result_of {
    
    template<typename T>
    struct get;
    
    }
    
    template<typename T>
    typename result_of::get<T>::type get()
    { return result_of::get<T>::apply(); }
    
    namespace result_of {
    
    template<>
    struct get<Tag1> {
        typedef double type;
    
        static type apply()
        { return 1.3; }
    };
    
    template<>
    struct get<Tag2> {
        typedef const char* type;
    
        static type apply()
        { return "hello"; }
    };
    
    }
    

    一般来说,特化类模板比特化函数模板更常见,而且看起来需要特化函数模板的情况通常通过让函数模板将其实现完全委托给类模板来简化。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-06
      • 2011-12-18
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      相关资源
      最近更新 更多