Home:ALL Converter>Template specialization with non-type

Template specialization with non-type

Ask Time:2018-03-30T22:39:29         Author:Aart Odding

Json Formatter

Considering I have a simple class template:

template <typename T>
class foo
{
    T t;
};

Is it possible to specialize foo such that T is not a type but a non-type value so that:

foo<float> my_foo;

Uses the class template shown above, while

foo<20> my_other_foo;

Uses a different template specialization? Is this possible, and if yes, what would the template specialization code look like?

Author:Aart Odding,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/49576418/template-specialization-with-non-type
max66 :

\n Is this possible, and if yes, what would the partial specialization code look like?\n\n\nAs you exactly want, no: it's impossible.\n\nBut, if you can use C++17, you can make almost the contrary: receiving an auto value (T become the declval() of the value)\n\ntemplate <auto Val>\nstruct foo\n {\n using T = decltype(Val);\n\n T t { Val }; // or also decltype(Val) t {Val};\n\n static constexpr bool isSpecialized { false };\n };\n\n\nyou can specialize for 20 (where 20 is an int; doesn't match (by example) 20L or 20U)\n\ntemplate <>\nstruct foo<20>\n {\n static constexpr bool isSpecialized { true };\n };\n\n\nThe problem of this solution is that you can't have foo<float> because a float value can't be a template not-type parameter (so you can't write foo<0.0f>, by example).\n\nYou can roughly bypass this problem adding a second template type parameter with a default value (the type of the first parameter)\n\ntemplate <auto Val, typename T = decltype(Val)>\nstruct bar\n {\n T t { Val };\n\n static constexpr bool isSpecialized { false };\n };\n\n\nand the 20 specialization remain\n\ntemplate <>\nstruct bar<20>\n {\n static constexpr bool isSpecialized { true };\n };\n\n\nbut now you can call bar<0, float> as substitute of the old foo<float>\n\nThe following is a full compiling (C++17, obviously) example\n\n#include <iostream>\n\ntemplate <auto Val>\nstruct foo\n {\n using T = decltype(Val);\n\n T t { Val }; // or also decltype(Val) t {Val};\n\n static constexpr bool isSpecialized { false };\n };\n\ntemplate <>\nstruct foo<20>\n {\n static constexpr bool isSpecialized { true };\n };\n\ntemplate <auto Val, typename T = decltype(Val)>\nstruct bar\n {\n T t { Val };\n\n static constexpr bool isSpecialized { false };\n };\n\ntemplate <>\nstruct bar<20>\n {\n static constexpr bool isSpecialized { true };\n };\n\nint main ()\n {\n std::cout << foo<0>::isSpecialized << std::endl; // print 0\n std::cout << foo<20>::isSpecialized << std::endl; // print 1\n std::cout << foo<20L>::isSpecialized << std::endl; // print 0\n\n std::cout << bar<0>::isSpecialized << std::endl; // print 0\n std::cout << bar<20>::isSpecialized << std::endl; // print 1\n std::cout << bar<20L>::isSpecialized << std::endl; // print 0\n std::cout << bar<20, float>::isSpecialized << std::endl; // print 0\n\n }\n",
2018-03-30T16:40:38
yy