我可以对类模板的函数模板成员进行单独定义吗?

Vor*_*ord 3 c++ templates specialization template-specialization function-templates

这是一个最小的代码示例,展示了我正在尝试的工作原理,但不是我希望的工作方式:

#include <string>
#include <type_traits>
#include <iostream>
struct string_tag {
    using R=const std::string;
};

struct int_tag {
    using R=const int;
};

template <bool TS>
class Wibble {
    public:
    template<typename TAG>
    typename TAG::R getValue(TAG);
};

template <bool TS>
template <typename TAG>
typename TAG::R Wibble<TS>::getValue(TAG) {
    if constexpr (std::is_same<TAG, string_tag>::value) {
        return "hello";
    }
    
    if constexpr (std::is_same<TAG, int_tag>::value) {
        return 42;
    }
}

// instantiate classes
template class Wibble<true>;
template class Wibble<false>;

int main () {
    Wibble<true> tw;
    Wibble<false> fw;
    std::cout << "tw string: " << tw.getValue(string_tag{}) << std::endl;
    std::cout << "tw int: " << tw.getValue(int_tag{}) << std::endl;
    std::cout << "fw string: " <<fw.getValue(string_tag{}) << std::endl;
    std::cout << "fw int: " << fw.getValue(int_tag{}) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

此处以 Godbolt 为例

我想要更改的部分是包含所有constexpr逻辑的丑陋的函数模板定义。我希望能够TAG独立定义不同的专业化,但这样做会给我带来redefinition of ...错误。

像下面这样的语法会很好:

template<bool TS>
template<>
string_tag::R Wibble<TS>::getValue(string_tag) {
  return "hello";
}
Run Code Online (Sandbox Code Playgroud)

但电脑说“不”。

ala*_*ner 5

我想了一下,阅读了语言规范等,然后我想到了以下事情:

\n
    \n
  1. 为了特化成员函数模板,类模板必须特化。时期。这是无法用概念来克服的,或者至少我还没有找到方法。我想您不想为每种 TS 情况复制代码。也许可以使用一些 Alexandrescu 风格的元编程技术自动完成,但我无法立即想到任何事情。

    \n
  2. \n
  3. 重载而不是模板是一个很好的选择,但我猜你希望能够将它们添加到线外,而不是在类内部......

    \n
  4. \n
  5. 然后我想起 David Wheeler:\xe2\x80\x9c 计算机科学中的所有问题都可以通过另一级间接来解决。”所以让我们添加一个:

    \n
  6. \n
\n
namespace detail\n{\ntemplate<typename TAG> auto getValue(TAG);\n\ntemplate<>\nauto getValue<string_tag>(string_tag)\n{\n    return "hi";\n}\n\n\ntemplate<>\nauto getValue<int_tag>(int_tag)\n{\n    return 42;\n}\n\ntemplate<>\nauto getValue<double_tag>(double_tag)\n{\n    return 1324.2;\n}\n\n}\n\ntemplate<bool TS>\ntemplate<typename TAG>\nauto Wibble<TS>::getValue(TAG t)\n{\n    return detail::getValue(t);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

https://godbolt.org/z/GsPK4MP8M \n希望有帮助。

\n